Spring-Security基于源码扩展-自定义认证失败返回(二十四)
默认是跳转页面,针对ajax请求我们需要返回json字符串
自定义认证我认为有2种 一种是登录验证 还有一种是未登录访问需要登录授权的页面
登录认证
一般都是使用默认登录或者继承AbstractAuthenticationProcessingFilter方式可以参考上一篇Spring-Security基于源码扩展-自定义登录(二十三)
设置对应的handle就行了如
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest() .authenticated() .and().rememberMe()//记住登录 .tokenRepository(new InMemoryTokenRepositoryImpl()) .and() .formLogin()// rm表单的方式 .loginPage("/login")//登录页面路径 .loginProcessingUrl("/doLogin") //自定义登录请求地址 .defaultSuccessUrl("/hello") .successHandler(new AuthenticationSuccessHandler() { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { String result="{\"code\":\"200\",\"message\":\"登录成功\"}"; response.getWriter().write(result); } }) .failureHandler(new AuthenticationFailureHandler(){ @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { //可以根据exception 获取我们验证登录时候的异常 定制化抛出异常 String result="{\"code\":\"403\",\"message\":\"登录失败\"}"; response.getWriter().write(result); } }) .usernameParameter("loginName") .passwordParameter("loginPassword") .permitAll(true)//不拦截 .and() .csrf()//记得关闭 .disable() .sessionManagement(). maximumSessions(1) .maxSessionsPreventsLogin(true); // }
未登录访问需要登录页面
Spring-security源码-Filter之FilterSecurityInterceptor(十九) 会进行统一的验证不通过会抛出异常
Spring-security源码-Filter之ExceptionTranslationFilter(十八)由此过滤器捕获处理
最终是交给authenticationEntryPoint处理参考源码<>
初始化是由FormLoginConfigure初始化的
org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer#loginPage
public FormLoginConfigurer<H> loginPage(String loginPage) { return super.loginPage(loginPage); }
protected T loginPage(String loginPage) { setLoginPage(loginPage); updateAuthenticationDefaults(); this.customLoginPage = true; return getSelf(); }
private void setLoginPage(String loginPage) { this.loginPage = loginPage; this.authenticationEntryPoint = new LoginUrlAuthenticationEntryPoint(loginPage); }
org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer#init
@Override public void init(B http) throws Exception { updateAuthenticationDefaults(); updateAccessDefaults(http); //注册 registerDefaultAuthenticationEntryPoint(http); }
所以我们本质就是只要给ExceptionHandlingConfigurer设置defaultAuthenticationEntryPointFor就行了
@SuppressWarnings("unchecked") protected final void registerDefaultAuthenticationEntryPoint(B http) { registerAuthenticationEntryPoint(http, this.authenticationEntryPoint); } @SuppressWarnings("unchecked") protected final void registerAuthenticationEntryPoint(B http, AuthenticationEntryPoint authenticationEntryPoint) { //获得ExceptionHandlingConfigurer 也就是初始化我们的ExceptionTranslationFilterConfiger ExceptionHandlingConfigurer<B> exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class); if (exceptionHandling == null) { return; } //设置 exceptionHandling.defaultAuthenticationEntryPointFor(postProcess(authenticationEntryPoint), getAuthenticationEntryPointMatcher(http)); }
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest() .authenticated() .and().rememberMe()//记住登录 .tokenRepository(new InMemoryTokenRepositoryImpl()) .and() .formLogin()// rm表单的方式 .loginPage("/login")//登录页面路径 .loginProcessingUrl("/doLogin") //自定义登录请求地址 .defaultSuccessUrl("/hello") .successHandler(new AuthenticationSuccessHandler() { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { String result="{\"code\":\"200\",\"message\":\"登录成功\"}"; response.getWriter().write(result); } }) .failureHandler(new AuthenticationFailureHandler(){ @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { //可以根据exception 获取我们验证登录时候的异常 丁世华抛出异常 String result="{\"code\":\"403\",\"message\":\"登录失败\"}"; response.getWriter().write(result); } }) .usernameParameter("loginName") .passwordParameter("loginPassword") .permitAll(true)//不拦截 .and() .exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPoint() { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { String result="{\"code\":\"403\",\"message\":\"您未登录\"}"; response.getWriter().write(result); } }).and() .csrf()//记得关闭 .disable() .sessionManagement(). maximumSessions(1) .maxSessionsPreventsLogin(true) ;