上一篇咱们说到如何在 spring security 中自定义登陆处理逻辑,这一篇咱们来说一下如何自定义登陆成功后的处理逻辑。先来回顾下默认状况下,登陆成功事后spring security 会帮咱们作些什么: 未登陆的状况下,咱们直接访问应用中的资源,页面会自动跳转到登陆页;当登陆成功后,页面会自动重定向到我登陆前请求的 url。html
好比:若是咱们想在登陆成功后,响应一个 json 字符串(包括“登陆成功”这样的提示信息,响应code,以及跳转的url)给前端。应该怎么办?前端
首先复制上一节的项目工程 spring-security-02,重命名为 Spring-security-03。 maven 依赖不须要改变,以下所示:git
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
定义登陆成功后的处理类 GoAuthenticationSuccessHandlergithub
/** * 自定义 登陆成功 处理类 */ [@Component](https://my.oschina.net/u/3907912) public class GoAuthenticationSuccessHandler implements AuthenticationSuccessHandler { @Autowired private ObjectMapper objectMapper; /** * {"code":200,"message":"操做成功","data":"登陆成功"} * [@param](https://my.oschina.net/u/2303379) request * [@param](https://my.oschina.net/u/2303379) response * [@param](https://my.oschina.net/u/2303379) authentication * @throws IOException * @throws ServletException */ @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { response.setHeader("Content-Type", "application/json;charset=utf-8"); response.getWriter().print(objectMapper.writeValueAsString(CommonResult.success("登陆成功"))); response.getWriter().flush(); } }
在 WebSecurityConfig 配置类中,注入自定义处理类的依赖 :web
@Autowired private GoAuthenticationSuccessHandler successHandler; @Autowired private GoAuthenticationFailureHandler failureHandler;
在 protected void configure(HttpSecurity http) 方法中,追加以下代码:spring
// 这些是原本就有的 http.formLogin() .loginPage("/loginPage.html")// 自定义登陆页 .loginProcessingUrl("/form/login")// 自定义登陆 action, 名字随便起 // 如下是新增的 .successHandler(successHandler)// 自定义登陆成功处理类 .failureHandler(failureHandler);// 自定义登陆失败处理类
从上面的代码中咱们能够看到,新增了两个配置,在 successHandler 和 failureHandler 方法中分别注入了一个处理类,咱们着重看下 GoAuthenticationSuccessHandler 处理类, 经过重写 AuthenticationSuccessHandler 的方法,响应了一段json给前端。 而failureHandler 是登陆失败时作一些处理,在这里咱们会响应登陆失败的message给前端。这些响应结果咱们均可以自定义。 你能够根据实际需求去选择是否须要自定义这些处理类。json
回顾一下,以前若是用户没有登陆直接访问咱们的应用资源,会自动跳转到登陆页,若是登陆成功后,去访问没有权限的url,会给咱们一段英文提示,大体意思就是没有权限。这些咱们仍然是能够定制的。好比当咱们没有登陆时,给前端提示“用户未登陆”,当咱们没有权限时,提示前端“用户没有权限”。app
定义两个处理类 GoAuthenticationEntryPoint 和 GoAccessDeniedHandlermaven
`ide
/** * 自定义 未登陆 或者 token 失效 处理类 */ @Component public class GoAuthenticationEntryPoint implements AuthenticationEntryPoint { @Autowired private ObjectMapper objectMapper; @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { response.setCharacterEncoding("UTF-8"); response.setContentType("application/json"); response.getWriter().println(objectMapper.writeValueAsString(CommonResult.unauthorized(authException.getMessage()))); response.getWriter().flush(); } } /** * 自定义没有访问权限处理类 */ @Component public class GoAccessDeniedHandler implements AccessDeniedHandler { @Autowired private ObjectMapper objectMapper; /** * @param request * @param response * @param e * @throws IOException * @throws ServletException * * @return {"code":403,"message":"没有相关权限","data":"Access is denied"} */ @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException { response.setHeader("Content-Type", "application/json;charset=utf-8"); response.getWriter().print(objectMapper.writeValueAsString(CommonResult.forbidden(e.getMessage()))); response.getWriter().flush(); } }
`
将自定义的两个处理类注入到 WebSecurityConfig 类中
` @Autowired private GoAccessDeniedHandler accessDeniedHandler;
@Autowired private GoAuthenticationEntryPoint entryPoint;
`
打开 WebSecurityConfig 配置类,在 configure 方法中追加以下代码:
@Override protected void configure(HttpSecurity http) throws Exception { // 此处省略一部分代码 http.exceptionHandling() .accessDeniedHandler(accessDeniedHandler)// 用户没有访问权限处理器 .authenticationEntryPoint(entryPoint);// 用户没有登陆处理器 }
上面咱们总共定义了四个处理类,分别做用于如下四种状况发生以后:
咱们能够根据实际状况选择性去定义这些处理类,根据具体需求去定义处理逻辑。详细代码能够参考 https://github.com/nimo10050/spring-security-sample/tree/master/spring-security-03