Spring Security(四):个性化用户认证流程

第三章已经可以从数据库查出密码进行各种校验了,但是对于各种登录认证流程来说还是单调,无法满足我们的企业级开发需求,本篇就进行一个个性化用户认证流程处理,包括自定义登录页面,自定义登录成功处理,自定义登陆失败处理。

自定义登录页面

自定义的登录页:meicloud-signIn.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
	<h2>标准登录页面</h2>
	<h3>表单登录</h3>
	<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>
</body>
</html>

配置自定义登录页

  • 在我们前面篇章讲到的 BrowserSecurityConfig 配置类中进行配置,如下 .loginPage()配置项
	@Override
	protected void configure(HttpSecurity http) throws Exception {
    
    
		http.formLogin()
				// 使用自定义的表单登录页面
				.loginPage("/meicloud-signIn.html")
				// 以下这行 UsernamePasswordAuthenticationFilter 会知道要处理表单的 /authentication/form 请求,而不是默认的 /login
				.loginProcessingUrl("/authentication/form")
				.and()
				.authorizeRequests()
				// 排除对 "/meicloud-signIn.html" 的身份验证
				.antMatchers("/meicloud-signIn.html").permitAll()
				// 表示所有请求都需要身份验证
				.anyRequest()
				.authenticated()
				.and()
				.csrf().disable();// 暂时把跨站请求伪造的功能关闭掉
	}
  • .loginProcessingUr()表示要处理表单的 /authentication/form 登录请求,而不是默认的 /login
  • 要注意的是,.anyRequest表示所有请求都需要身份验证,导致我们的登录页/meicloud-signIn.html也需要进行身份验证,所以我们需要配置.antMatchers("/meicloud-signIn.html").permitAll()来使得登录页不需要进行拦截认证。

自定义登录成功处理

实现AuthenticationSuccessHandler接口,实现onAuthenticationSuccess()方法

  • 但是一般情况下不会去直接实现该接口,一般可以继承该接口的实现类,如下,这样使得给到前端的请求有更多种选择,比如JSON或者是跳到另一个路径。
@Component("meicloudAuthenticationSuccessHandler")
public class MeicloudAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
    
    

	private Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	private ObjectMapper objectMapper;
	@Autowired
	private SecurityProperties securityProperties;
	private RequestCache requestCache = new HttpSessionRequestCache();

	/**
	 * 登录成功处理
	 * @param authentication 封装认证信息,包括认证请求信息,ip、session信息等,还包括认证通过以后,自定义的UserDetailService返回的UserDetails信息
	 */
	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication authentication) throws IOException, ServletException {
    
    
		logger.info("登录成功");

		if (LoginResponseType.JSON.equals(securityProperties.getBrowser().getSignInResponseType())) {
    
    
			response.setContentType("application/json;charset=UTF-8");
			String type = authentication.getClass().getSimpleName();
			response.getWriter().write(objectMapper.writeValueAsString(new SimpleResponse(type)));
		} else {
    
    
			// 如果设置了meicloud.security.browser.singInSuccessUrl,总是跳到设置的地址上
			// 如果没设置,则尝试跳转到登录之前访问的地址上,如果登录前访问地址为空,则跳到网站根路径上
			if (StringUtils.isNotBlank(securityProperties.getBrowser().getSingInSuccessUrl())) {
    
    
				requestCache.removeRequest(request, response);
				setAlwaysUseDefaultTargetUrl(true);
				setDefaultTargetUrl(securityProperties.getBrowser().getSingInSuccessUrl());
			}
			super.onAuthenticationSuccess(request, response, authentication);
		}
	}
}
  • 然后需要在 BrowserSecurityConfig 配置类中进行配置,加上一行 .successHandler() 配置
	@Override
	protected void configure(HttpSecurity http) throws Exception {
    
    
		http.formLogin()
				.loginPage("/meicloud-signIn.html")
				.loginProcessingUrl("/authentication/form")
				// 配置成功处理
				.successHandler(meicloudAuthenticationSuccessHandler)
				.and()
				.authorizeRequests()
				.antMatchers("/meicloud-signIn.html").permitAll()
				.anyRequest()
				.authenticated()
				.and()
				.csrf().disable();
	}

自定义登陆失败处理

和登录成功处理类似,实现 AuthenticationFailHandler 接口,实现onAuthenticationFailure()方法

  • 同理一样不会去直接实现该接口,可以继承它的实现类 SimpleUrlAuthenticationFailureHandler
 @Component("meicloudAuthenctiationFailureHandler")
class MeicloudAuthencationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
    
    

    private Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private SecurityProperties securityProperties;

    /**
     * 登录失败处理
     * @param exception 包含了登录错误时的异常,包括用户名没找着、密码不正确等等
     */
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
                                        AuthenticationException exception) throws IOException, ServletException {
    
    

        logger.info("登录失败");

        if (LoginResponseType.JSON.equals(securityProperties.getBrowser().getSignInResponseType())) {
    
    
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(objectMapper.writeValueAsString(new SimpleResponse(exception.getMessage())));
        }else{
    
    
            super.onAuthenticationFailure(request, response, exception);
        }

    }
}
  • 同样需要在 BrowserSecurityConfig 中添加 .failureHandler() 配置
	@Override
	protected void configure(HttpSecurity http) throws Exception {
    
    
		http.formLogin()
				.loginPage("/meicloud-signIn.html")
				.loginProcessingUrl("/authentication/form")
				// 配置成功处理
				.successHandler(meicloudAuthenticationSuccessHandler)
				.failureHandler(meicloudAuthenticationFailureHandler)
				.and()
				.authorizeRequests()
				.antMatchers("/meicloud-signIn.html").permitAll()
				.anyRequest()
				.authenticated()
				.and()
				.csrf().disable();
	}

总结

需求 实现
自定义登录页面 http.formLogin().loginPage("/meicloud-signIn.html")
自定义登录成功处理 AuthenticationSuccessHandler
自定义登录失败处理 AuthenticationFailureHandler

猜你喜欢

转载自blog.csdn.net/qq_36221788/article/details/105478847
今日推荐