013 个性化用户认证流程

Posted 曹军

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了013 个性化用户认证流程相关的知识,希望对你有一定的参考价值。

一:任务

1.任务

  自定义登录页面

  自定义登录成功处理

  自定义登录失败处理

 

二:自定义登录页面

1.说明

  在security中,默认的登录处理是

  

 

2.BrowserSecurityConfig

  这里从新定义登录的页面,与登录方法

 1 package com.cao.security.browser;
 2 
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.Configuration;
 5 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 6 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 7 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 8 import org.springframework.security.crypto.password.PasswordEncoder;
 9 /**
10  * 覆盖掉security原有的配置
11  * @author dell
12  *
13  */
14 @Configuration
15 public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter{
16     @Override
17     protected void configure(HttpSecurity http) throws Exception {
18         //表单登陆的一个安全认证环境
19         http.formLogin()
20             .loginPage("/index.html")
21             .loginProcessingUrl("/authentication/form")
22 //        http.httpBasic()
23             .and()
24             .authorizeRequests()    //请求授权
25             .antMatchers("/index.html").permitAll()  //这个url不需要认证
26             .anyRequest()            //任何请求
27             .authenticated()         //都需要认证
28             .and()
29             .csrf().disable();      //去掉csrf的防护
30         
31     }
32     
33     @Bean
34     public PasswordEncoder passwordEncoder() {
35         return new BCryptPasswordEncoder();
36     }
37 }

 

3.index.htnl

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4 <meta charset="UTF-8">
 5 <title>登录</title>
 6 </head>
 7 <body>
 8     <h2>标准登录页面</h2>
 9     <h3>表单登录</h3>
10     <form action="/authentication/form" method="post">
11         <table>
12             <tr>
13                 <td>用户名</td>
14                 <td><input type="text" name="username"></td>
15             </tr>
16             <tr>
17                 <td>密码</td>
18                 <td><input type="password" name="password"></td>
19             </tr>
20             <tr>
21                 <td colspan="2"><button type="submit">登录</button></td>
22             </tr>
23         </table>
24     </form>
25 </body>
26 </html>

 

4.登录界面

  

 

三:优化

1.问题

  现在的处理是接收到html请求,然后直接跳转到了html登录页面

  因为,这里优化一下比较好,做到统一处理。

  现在的优化方法如下:

  

 

2.先修改配置类

  这里说明,进入的显示控制类,然后由控制类进行决定走哪里

  这里还包含了自定义的url不进过认证,这里的程序先粘贴过来了。

 1 package com.cao.security.browser;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.context.annotation.Bean;
 5 import org.springframework.context.annotation.Configuration;
 6 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 7 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 8 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 9 import org.springframework.security.crypto.password.PasswordEncoder;
10 
11 import com.cao.security.core.properties.SecurityProperties;
12 /**
13  * 覆盖掉security原有的配置
14  * @author dell
15  *
16  */
17 @Configuration
18 public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter{
19     @Autowired
20     private SecurityProperties securityProperties;
21     
22     @Override
23     protected void configure(HttpSecurity http) throws Exception {
24         //表单登陆的一个安全认证环境
25         http.formLogin()
26             .loginPage("/authentication/require")
27             .loginProcessingUrl("/authentication/form")
28 //        http.httpBasic()
29             .and()
30             .authorizeRequests()    //请求授权
31             .antMatchers("/authentication/require",
32                     securityProperties.getBrowser().getLoginPage()).permitAll()  //这个url不需要认证,包含自定义的登录页
33             .anyRequest()            //任何请求
34             .authenticated()         //都需要认证
35             .and()
36             .csrf().disable();      //去掉csrf的防护
37         
38     }
39     
40     @Bean
41     public PasswordEncoder passwordEncoder() {
42         return new BCryptPasswordEncoder();
43     }
44 }

 

3.控制类

  这里直接读取的是可以自定义的页面,后续会添加如何引入的。

 1 /**
 2  * 
 3  */
 4 package com.cao.security.browser;
 5 
 6 import java.io.IOException;
 7 
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10 
11 import org.apache.commons.lang.StringUtils;
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
14 import org.springframework.beans.factory.annotation.Autowired;
15 import org.springframework.http.HttpStatus;
16 import org.springframework.security.web.DefaultRedirectStrategy;
17 import org.springframework.security.web.RedirectStrategy;
18 import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
19 import org.springframework.security.web.savedrequest.RequestCache;
20 import org.springframework.security.web.savedrequest.SavedRequest;
21 import org.springframework.web.bind.annotation.RequestMapping;
22 import org.springframework.web.bind.annotation.ResponseStatus;
23 import org.springframework.web.bind.annotation.RestController;
24 
25 import com.cao.security.browser.support.SimpleResponse;
26 import com.cao.security.core.properties.SecurityProperties;
27 
28 /**
29  * @author dell
30  *
31  */
32 @RestController
33 public class BrowserSecurityController {
34     private Logger logger=LoggerFactory.getLogger(getClass());
35     //拿到引气身份跳转的请求
36     //因为在跳转之前,security会将请求缓存到session中
37     private RequestCache requestCache=new HttpSessionRequestCache();
38     
39     //跳转
40     private RedirectStrategy redirectStrategy=new DefaultRedirectStrategy();
41     
42     //方便读取自定义登录页的配置项
43     @Autowired
44     private SecurityProperties securityProperties;
45 
46     /**
47      * 当需要身份认证的时候,跳转到这里
48      * @param request
49      * @param response
50      * @return
51      * @throws Exception 
52      */
53     @RequestMapping("/authentication/require")
54     @ResponseStatus(code=HttpStatus.UNAUTHORIZED)
55     public SimpleResponse requiredAuthentication(HttpServletRequest request,HttpServletResponse response) throws Exception {
56         SavedRequest saveRequest=requestCache.getRequest(request, response);
57         if(saveRequest!=null) {
58             String target=saveRequest.getRedirectUrl();
59             logger.info("引发跳转的请求:"+target);
60             if(StringUtils.endsWithIgnoreCase(target, ".html")) {
61                 //跳转到一个自定义的登录页
62                 redirectStrategy.sendRedirect(request, response, securityProperties.getBrowser().getLoginPage());
63             }
64         }
65         return new SimpleResponse("访问的服务需要身份认证,请引导到登录页");
66     }
67 }

   返回值,需要一个类。SimpleResponse.java

 1 package com.cao.security.browser.support;
 2 
 3 public class SimpleResponse {
 4     public SimpleResponse(Object content) {
 5         this.content=content;
 6     }
 7     
 8     private Object content;
 9 
10     public Object getContent() {
11         return content;
12     }
13 
14     public void setContent(Object content) {
15         this.content = content;
16     }
17     
18 }

 

4.系统配置封装

  方便统一管理用户的配置项。

  

 

5.新建SecurityProperties

  这里是最外层的一层包装

  同时。这里需要放入在core的项目下。

  

  首先,这里会读取的是jun.security开头的配置项,同时会把配置项的第三个字段读取到同browser相同的类中。所以,后续还要写browser的类。

 1 package com.cao.security.core.properties;
 2 
 3 import org.springframework.boot.context.properties.ConfigurationProperties;
 4 
 5 @ConfigurationProperties(prefix="jun.security")
 6 public class SecurityProperties {
 7     private BrowserProperties browser=new BrowserProperties();
 8 
 9     public BrowserProperties getBrowser() {
10         return browser;
11     }
12 
13     public void setBrowser(BrowserProperties browser) {
14         this.browser = browser;
15     }
16 
17     
18 }

 

6.BrowserProperties.java

  这里要读取的是配置项的第四个字段,这里需要的是不能乱写。

  loginPage这里有一个默认值,如果用户没有给,就使用初始化的值。

 1 package com.cao.security.core.properties;
 2 
 3 public class BrowserProperties {
 4 
 5     private String loginPage="/index.html";
 6 
 7     public String getLoginPage() {
 8         return loginPage;
 9     }
10 
11     public void setLoginPage(String loginPage) {
12         this.loginPage = loginPage;
13     }
14     
15 }

 

7.SecurityConfig.java

  这里是的配置项的类生效,这里的类写最外层的即可。

 1 package com.cao.security.core.properties;
 2 
 3 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 4 import org.springframework.context.annotation.Configuration;
 5 
 6 @Configuration
 7 //让SecurityProperties读取器生效
 8 @EnableConfigurationProperties(SecurityProperties.class)
 9 public class SecurityCoreConfig {
10 
11 }

 

8.自定义的配置项

  这里写在demo项目中。

 1 ##JDBC
 2 spring.datasource.driver-class-name = com.mysql.jdbc.Driver
 3 spring.datasource.url= jdbc:mysql://127.0.0.1:3308/test?useUnicode=yes&characterEncoding=UTF-8&useSSL=false
 4 spring.datasource.username = root
 5 spring.datasource.password = 123456
 6 
 7 ##session store type
 8 spring.session.store-type=none
 9 
10 ##server port
11 #server.port=8060
12 
13 ##security login
14 #security.basic.enabled = false
15 
16 jun.security.browser.loginPage=/newIndex.html

 

9.效果

  访问:http://localhost:8080/user/

  

 

  访问:newIndex.html

  

 

  访问:http://localhost:8080/index.html

  

 

四:登录成功后的处理

1.修改初始化的配置

  主要是说明登录成功后使用自定义的类

 1 package com.cao.security.browser;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.context.annotation.Bean;
 5 import org.springframework.context.annotation.Configuration;
 6 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 7 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 8 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 9 import org.springframework.security.crypto.password.PasswordEncoder;
10 import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
11 
12 import com.cao.security.browser.authentication.BrowserAuthenticationSucceswsHandler;
13 import com.cao.security.core.properties.SecurityProperties;
14 /**
15  * @Description 覆盖掉security原有的配置
16  * @author dell
17  *
18  */
19 @Configuration
20 public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter{
21     //获取自定义的登录页面
22     @Autowired
23     private SecurityProperties securityProperties;
24     
25     //使用自己的登录成功后的处理类
26     @Autowired
27     private AuthenticationSuccessHandler browserAuthenticationSucceswsHandler;
28     
29     
30     @Override
31     protected void configure(HttpSecurity http) throws Exception {
32         //表单登陆的一个安全认证环境
33         http.formLogin()
34             .loginPage("/authentication/require")
35             .loginProcessingUrl("/authentication/form")
36             .successHandler(browserAuthenticationSucceswsHandler)
37 //        http.httpBasic()
38             .and()
39             .authorizeRequests()    //请求授权
40             .antMatchers("/authentication/require",
41                     securityProperties.getBrowser().getLoginPage()).permitAll()  //这个url不需要认证,包含自定义的登录页
42             .anyRequest()            //任何请求
43             .authenticated()         //都需要认证
44             .and()
45             .csrf().disable();      //去掉csrf的防护
46         
47     }
48     
49     @Bean
50     public PasswordEncoder passwordEncoder() {
51         return new BCryptPasswordEncoder();
52     }
53 }

 

2.登录成功处理类

 1 package com.cao.security.browser.authentication;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.ServletException;
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 
 9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory;
11 import org.springframework.beans.factory.annotation.Autowired;
12 import org.springframework.security.core.Authentication;
13 import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
14 import org.springframework.stereotype.Component;
15 
16 import com.fasterxml.jackson.databind.ObjectMapper;
17 
18 @Component(value="browserAuthenticationSucceswsHandler")
19 public class BrowserAuthenticationSucceswsHandler implements AuthenticationSuccessHandler {
20     private Logger logger=LoggerFactory.getLogger(getClass());
21     
22     @Autowired
23     private ObjectMapper objectMapper;
24 
25     /**
26      * @Description 登录成功会被调用
27      */
28     @Override
29     public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
30             Authentication authentication) throws IOException, ServletException {
31         //Authentication 封装了认证信息
32         logger.info("登录成功");
33         response.setContentType("application/json;charset=UTF-8");
34         //将authentication转为json字符串
35         response.getWriter().write(objectMapper.writeValueAsString(authentication));
36     }
37 
38 }

 

3.效果

  登录成功后的authentication的json格式如下:

  

 

五:登录失败后的处理

1.修改初始化的配置

 1 package com.cao.security.browser;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.context.annotation.Bean;
 5 import org.springframework.context.annotation.Configuration;
 6 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 7 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 8 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 9 import org.springframework.security.crypto.password.PasswordEncoder;
10 import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
11 
12 import com.cao.security.browser.authentication.BrowserAuthenticationFailHandler;
13 import com.cao.security.browser.authentication.BrowserAuthenticationSucceswsHandler;
14 import com.cao.security.core.properties.SecurityProperties;
15 /**
16  * @Description 覆盖掉security原有的配置
17  * @author dell
18  *
19  */
20 @Configuration
21 public class BrowserSecurityCo

以上是关于013 个性化用户认证流程的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段15——git命令操作一个完整流程

VSCode自定义代码片段15——git命令操作一个完整流程

个性化用户认证流程

spring-security 个性化用户认证流程——自定义登录页面(可配置)

spring-security 个性化用户认证流程——自定义登录成功/失败的处理

个性化推荐系统推荐算法