SpringSecurity-5-自定义登录验证
- 默认登录成功失败跳转页
- 为什么自定义登录验证结果处理场景
- 自定义登录成功的结果处理
- 自定义登录失败的结果处理
- 自定义权限访问异常结果处理
默认登录成功失败跳转页
如果我们 登录成功,由接口AuthenticationSuccessHandler进行登录结果处理,默认会使用SimpleUrlAuthenticationSuccessHandler,是AuthenticationSuccessHandler的实现类,SimpleUrlAuthenticationSuccessHandler核心代码如下
public class SimpleUrlAuthenticationSuccessHandler extends AbstractAuthenticationTargetUrlRequestHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { handle(request, response, authentication); clearAuthenticationAttributes(request); } }
在抽象类AbstractAuthenticationTargetUrlRequestHandler,我们可以发现,其默认**defaultTargetUrl = /**,核心代码如下
在本例子中我们的**/页面为inxde.html**,实现代码如下
// 首页 @RequestMapping({"/index", "/", ""}) public String index() { return "index"; }
因此登录成功后跳转到http://localhost:8080/,**如果我们不想默认跳转页面为/**,我们可以进行设置,如下图所示
- 当登录失败的时候,是由AuthenticationfailureHandler进行登录结果处理,默认跳转到failureUrl配置的路径对应的资源页面(一般也是跳转登录页login.html,重新登录)。
为什么自定义登录验证结果处理场景
- 前后端分离,后端返回结果应该是JSON
- 实现千人千面(不同的人,登录后向不同的页面跳转)
自定义登录成功的结果处理
AuthenticationSuccessHandler完成登录成功处理
- 创建MyAuthenticationSuccessHandler类直接实现AuthenticationSuccessHandler接口
注意:实现类上不要少了注解 @Component注解
@Component public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler { private static ObjectMapper objectMapper = new ObjectMapper(); @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { // 当认证成功后,响应 JSON 数据给前端 response.setContentType("application/json;charset=UTF-8"); response.getWriter().write(objectMapper.writeValueAsString("test登录成功")); } }
在 LearnSrpingSecurity中注入 和 引用自定义认证成功处理器 MyAuthenticationSuccessHandler,实现代码如下
- 测试
重启项目,访问http://localhost:8080跳转到登录页面,登录成功后结果为
继承SavedRequestAwareAuthenticationSuccessHandler实现登录成功处理
继承SavedRequestAwareAuthenticationSuccessHandler 类的话,他会记住我们上一次请求的资源路径,比如:用户请求syslog.html,没有登录所以被拦截到了登录页,当你登录成功之后会自动跳转到syslog.html,而不是主页面。代码实现如下
@Component public class MySavedRequestAwareAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { //在application配置文件中配置登录的类型是JSON数据响应还是做页面响应 @Value("${login.success.type}") private String loginType; //Jackson JSON数据处理类 private static ObjectMapper objectMapper = new ObjectMapper(); @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException { if (loginType.equalsIgnoreCase("JSON")) { response.setContentType("application/json;charset=UTF-8"); response.getWriter().write(objectMapper.writeValueAsString("test Saved 登录成功")); } else { // 会帮我们跳转到上一次请求的页面上 super.onAuthenticationSuccess(request, response, authentication); } } }
在application.properties中配置login.success.type
login.success.type=HTML #设置为html或者json,如果为json返回json
- 测试
使用浏览器访问http://localhost:8080/sysuser,登录成功后,页面显示为
自定义登录失败的结果处理
AuthenticationFailureHandler实现登录失败验证
- 创建MyAuthenticationFailureHandler类实现AuthenticationFailureHandler接口
注意:实现类上不要少了注解 @Component注解
@Component public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler { private static ObjectMapper objectMapper = new ObjectMapper(); @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { // 当认证失败后,响应 JSON 数据给前端 response.setContentType("application/json;charset=UTF-8"); response.getWriter().write(objectMapper.writeValueAsString("test登录失败")); } }
- 在 LearnSrpingSecurity中注入 和 引用自定义认证成功处理器 MyAuthenticationFailureHandler,实现代码如下
- 测试
访问http://localhost:8080/login/form,输入错误的用户名和密码,结果如下
SimpleUrlAuthenticationFailureHandler 实现登录失败处理
继承SimpleUrlAuthenticationFailureHandler 类。该类中默认实现了登录验证失败的跳转逻辑,即登录失败之后回到登录页面。我们可以利用这一点简化我们的代码。实现代码如下
@Component public class MySimpleUrlAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { //在application配置文件中配置登录的类型是JSON数据响应还是做页面响应 @Value("${login.success.type}") private String loginType; private static ObjectMapper objectMapper = new ObjectMapper(); @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { if (loginType.equalsIgnoreCase("JSON")) { response.setContentType("application/json;charset=UTF-8"); response.getWriter().write( objectMapper.writeValueAsString("用户名或密码存在错误,请检查后再次登录")); } else { response.setContentType("text/html;charset=UTF-8"); super.onAuthenticationFailure(request, response, exception); } } }
其他步骤和AuthenticationFailureHandler实现登录失败验证的步骤一致。
自定义权限访问异常结果处理
除了登录成功、登录失败的结果处理,Spring Security还为我们提供了其他的结果处理类。比如用户未登录就访问系统资源
AuthenticationEntryPoint 用来解决匿名用户访问无权限资源时的异常
- 代码实现如下
注意:实现类上不要少了注解 @Component注解
@Component public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint { //Jackson JSON数据处理类 private static ObjectMapper objectMapper = new ObjectMapper(); @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { response.setCharacterEncoding("utf-8"); response.setContentType("text/javascript;charset=utf-8"); response.getWriter().print(objectMapper.writeValueAsString("没有访问权限!")); } }
AccessDeniedHandler解决认证用户没有访问权限
注意:实现类上不要少了注解 @Component注解
@Component public class MyAccessDeineHandler implements AccessDeniedHandler { //Jackson JSON数据处理类 private static ObjectMapper objectMapper = new ObjectMapper(); @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { response.setCharacterEncoding("utf-8"); response.setContentType("text/javascript;charset=utf-8"); response.getWriter().print(objectMapper.writeValueAsString("认证用户没有访问权限!")); } }
在 LearnSrpingSecurity中注入MyAccessDeineHandler和MyAuthenticationEntryPoint实现如下
如果您觉得本文不错,欢迎关注,点赞,收藏支持,您的关注是我坚持的动力!