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)
        ;

 

posted @ 2021-11-15 17:45  意犹未尽  阅读(383)  评论(0编辑  收藏  举报