SpringSecurity(三)个性化用户认证流程

个性化用户认证流程

一.自定义登录页面

1.创建html文件,(Springboot项目html文件路径在resources/static/imooc-signIn.html),该表单登录请求为post请求,具体url为 /authentication/form

<form action="/authentication/form" method="post">
    <table>
        <tr>
            <td>用户名:</td>
            <td><input type="text" name="username"></td>
        </tr>
        <tr>
            <td>密码:</td>
            <td><input type="password" name="password"></td>
        </tr>
        <tr>
            <td colspan="2">
                <button type="submit">登录</button>
            </td>
        </tr>
    </table>
</form>

2.配置文件中 SecurityConfig中的 configure方法中,更改为:

http.formLogin()
    .loginPage("/imooc-signIn.html")       //所有请求跳转至登录页面
    .loginProcessingUrl("/authentication/form")    //UsernamePasswordAuthenticationFilter处理该请求
    .and()
    .authorizeRequests()
    .antMatchers("/imooc-signIn.html").permitAll()  //对该请求不进行身份认证
    .anyRequest()
    .authenticated()
    .and().csrf().disable();      //disable掉跨站防护功能

3.前两步的登录适用于返回html页面,但在前后端分离的项目中,返回的不一定是一个html页面,也有可能是一段json代码。故对代码进行改造。

在这里插入图片描述

4.新增一个接口

@RestController
@Slf4j
public class SecurityController {

    private RequestCache requestCache = new HttpSessionRequestCache();

    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    /**
     * 当需要身份认证时,跳转到这里
     */
    @RequestMapping("/authentication/require")
    @ResponseStatus(code = HttpStatus.UNAUTHORIZED)
    public SimpleResponse requireAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException {
        SavedRequest savedRequest = requestCache.getRequest(request,response);
        if(savedRequest!=null){
            String targetUrl = savedRequest.getRedirectUrl();
            log.info("引发跳转的请求是:"+targetUrl);
            if(StringUtils.endsWithIgnoreCase(targetUrl,".html")){
                redirectStrategy.sendRedirect(request,response,targetUrl);
            }
        }
        return new SimpleResponse("访问的服务需要身份认证,请引导用户至登录页");
    }
}

5.其中返回对象的结构

@Data
public class SimpleResponse {
    private Object content;
    public SimpleResponse(Object content) {
        this.content = content;
    }
}

6.SecurityConfig中的 configure方法中,更改为:

http.formLogin()
    .loginPage("/authentication/require")
    .loginProcessingUrl("/authentication/form")
    .and()
    .authorizeRequests()
    .antMatchers("/imooc-signIn.html","/authentication/require").permitAll()
    .anyRequest()
    .authenticated()
    .and().csrf().disable();
二.如何让用户可以自己去配置登录页面
  1. 创建html文件

  2. 在application.yml中进行配置

    imooc:
      security:
        browser:
          loginPage: /imooc-signIn.html
    
  3. 创建对象,

    @Data
    @ConfigurationProperties(prefix = "imooc.security")
    public class SecurityProperties {
        private BrowserProperties browser = new BrowserProperties();
    }
    
    @Data
    public class BrowserProperties {
        private String loginPage = "/demo-signIn.html";
    }
    

    在SecurityConfig配置类上使用注解@EnableConfigurationProperties(SecurityProperties.class)将SecurityProperties进行bean加载

  4. 使用

    @Autowired
    private SecurityProperties securityProperties;
    
    securityProperties.getBrowser().getLoginPage();
    

    如果用户没有配置,则使用loginPage的默认值,如果进行了配置,则使用用户配置的html页面

三.自定义登录成功和失败流程

1.创建自定义登录成功处理器

	/**
	 * 自定义登录成功处理
	 */
	@Component("imoocAuthenticationSuccessHandler")
	@Slf4j
	public class ImoocAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
	
	    @Autowired
	    private ObjectMapper objectMapper;
	
	    @Override
	    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
	                                        Authentication authentication) throws IOException, ServletException {
	        log.info("登录成功");
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(objectMapper.writeValueAsString(authentication)); 
	    }
	}

2.创建自定义登录失败处理器

	@Slf4j
	@Component("imoocAuthenticationFailureHandler")
	public class ImoocAuthenticationFailureHandler implements AuthenticationFailureHandler {
	
	    @Autowired
	    private ObjectMapper objectMapper;
	
	    @Override
	    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
	                                        AuthenticationException e) throws IOException, ServletException {
	        log.info("登录失败");
	
	        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
	        response.setContentType("application/json;charset=UTF-8");
	        response.getWriter().write(objectMapper.writeValueAsString(new SimpleResponse(e.getMessage())));
	    }
	}

3.在使用该处理器的类中注入config

	@Autowired
    private AuthenticationSuccessHandler imoocAuthenticationSuccessHandler;

	@Autowired
	private LoginAuthenticationFailureHandler loginAuthenticationFailureHandler;

4.SecurityConfig中的 configure方法中,更改为:

	http.formLogin()
    .loginPage("/authentication/require")
    .loginProcessingUrl("/authentication/form")
    .successHandler(imoocAuthenticationSuccessHandler)
	.failureHandler(loginAuthenticationFailureHandler)  
    .and()
    .authorizeRequests()
    .antMatchers(securityProperties.getBrowser().getLoginPage(),
            "/authentication/require").permitAll()
    .anyRequest()
    .authenticated()
    .and().csrf().disable();

5.如需将成功和失败处理做成可配置的,则需要如下改动

## 1. 成功和失败处理器分别继承如下接口
	ImoocAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler
	ImoocAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler

##2. 创建枚举,用来保存登录的方式
	public enum LoginType {
	    REDIRECT,
	    JSON,
	    ;
	}
	
##3.  在BrowserProperties配置类中添加loginType属性
	@Data
	public class BrowserProperties {
	    private String loginPage = "/demo-signIn.html";
		private LoginType loginType = LoginType.JSON;
	}

##4. 成功处理器和失败处理器中进行分情况处理
	成功处理器中逻辑为
	if(LoginType.JSON.equals(securityProperties.getBrowser().getLoginType())){
        log.info("登录成功");
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(objectMapper.writeValueAsString(authentication));
    }else {
        super.onAuthenticationSuccess(request,response,authentication);
    }

	失败处理器中逻辑为
	log.info("登录失败");
    if(LoginType.JSON.equals(securityProperties.getBrowser().getLoginType())){
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        response.setContentType("application/json;charset=UTF-8");
        //返回前台不需要返回所有信息,只需要返回错误信息即可
        response.getWriter().write(objectMapper.writeValueAsString(new SimpleResponse(e.getMessage())));
    }else {
        super.onAuthenticationFailure(request,response,e);
    }

##5. 在yml文件中配置属性
	imooc:
	  security:
	    browser:
	      loginType: REDIRECT
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值