首页 > 其他分享 >Spring Security(4)

Spring Security(4)

时间:2022-11-24 07:55:51浏览次数:38  
标签:自定义 Spring void public 处理器 登出 Security response

您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~

 

前面的方法中,除了login()方法能成功,另外两个都失败,并不是因为代码问题,而是Spring Security默认是通过Web页面来实现页面逻辑跳转的。但在前后端分离的开发模式中,页面跳转的逻辑后端已经无法直接控制了,而是通过返回状态码由前端来执行跳转。因此,需要对应用进行改造。

首先自定义认证成功处理器,也就是实现AuthenticationSuccessHandler接口:

/**
 * 自定义认证成功处理器
 *
 * @author 湘王
 */
@Component
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication) throws IOException, ServletException {
        System.out.println("登录成功");

        // 前后端分离的调用方式
        response.setStatus(HttpStatus.OK.value());
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write("OK");
    }
}

 

 

 

接着来实现之前没有的认证失败处理器AuthenticationFailureHandler:

/**
 * 自定义认证失败处理器
 *
 * @author 湘王
 */
@Component
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
                                        AuthenticationException exception) throws IOException, ServletException {
        System.out.println("user or password error");

        // 前后端分离的调用方式
        response.setStatus(HttpStatus.OK.value());
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write("user or password error");
    }
}

 

 

再实现登出处理器LogoutSuccessHandler:

/**
 * 自定义登出处理器
 *
 * @author 湘王
 */
@Component
public class CustomLogoutSuccessHandler implements LogoutSuccessHandler {
    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
                                Authentication authentication) throws IOException, ServletException {
        System.out.println("登出成功");

        // 前后端分离的调用方式
        response.setStatus(HttpStatus.OK.value());
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write("OK");
    }
}

 

 

然后修改之前的修改WebSecurityConfiguration,让过滤器中增加对这几个处理器的支持:

// 控制逻辑
@Override
protected void configure(HttpSecurity http) throws Exception {
    // 执行UsernamePasswordAuthenticationFilter之前添加拦截过滤
    http.addFilterBefore(new CustomInterceptorFilter(), UsernamePasswordAuthenticationFilter.class);

    http.authorizeRequests()
            .anyRequest().authenticated()
            // 设置自定义认证成功、失败及登出处理器
            .and().formLogin().loginPage("/login")
            .successHandler(successHandler).failureHandler(failureHandler).permitAll()
            .and().logout().logoutUrl("/logout").deleteCookies("JSESSIONID")
            .logoutSuccessHandler(logoutSuccessHandler).permitAll()
            // 跨域访问
            .and().cors()
            .and().csrf().disable();
}

 

 

现在再次测试LoginController中的登录和登出操作,可以看到它们都能成功执行。目前权限已经做到了与Controller中的业务逻辑无关了。

 

但是仅仅做到登录、登出操作肯定是不行的,这连Demo都不如。所以接下里,来看看一个比较核心的问题:用户角色是否有效(不然建角色表干嘛)。

先在LoginController类中加入下面两个方法:

@GetMapping("/admin")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public String admin() {
    return "admin有ROLE_ADMIN角色";
}

@GetMapping("/manager")
@PreAuthorize("hasRole('ROLE_MANAGER')")
public String manager() {
    return "manager有ROLE_MANAGER角色";
}

 

 

启动应用,运行postman时会发现:

1、用admin登录,访问localhost:8080/admin正常,但访问localhost:8080/manager就出现Forbidden错误;

2、用manager登录,访问localhost:8080/manager正常,而访问localhost:8080/admin也出现Forbidden错误。

这说明用户角色权限已经起作用了,但显示Forbidden的方式不够友好。所以再来增加一个自定义处理器,也就是实现AccessDeniedHandler接口,让访问拒绝友好一些:

/**
 * 自定义访问被拒绝
 *
 * @author 湘王
 */
@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
                       AccessDeniedException exception) throws IOException, ServletException {
        System.out.println("permission denied");

        // 前后端分离的调用方式
        response.setStatus(HttpStatus.OK.value());
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write("permission denied");
    }
}

 

 

然后同样地,要在WebSecurityConfiguration过滤器链中增加这个新增的过滤器:

// 控制逻辑
@Override
protected void configure(HttpSecurity http) throws Exception {
    // 执行UsernamePasswordAuthenticationFilter之前添加拦截过滤
    http.addFilterBefore(new CustomInterceptorFilter(), UsernamePasswordAuthenticationFilter.class);

    http.authorizeRequests()
        .anyRequest().authenticated()
        // 设置自定义认证成功、失败及登出处理器
        .and().formLogin().loginPage("/login")
        .successHandler(successHandler).failureHandler(failureHandler).permitAll()
        .and().logout().logoutUrl("/logout").deleteCookies("JSESSIONID")
        .logoutSuccessHandler(logoutSuccessHandler).permitAll()
        // 配置无权访问的自定义处理器
        .and().exceptionHandling().accessDeniedHandler(accessDeniedHandler)
        .and().cors()
        .and().csrf().disable();
}

 

 

再用postman进行测试的时候就能看到,现在的提示现在已经比刚才要友好了。

 

 


 

 

感谢您的大驾光临!咨询技术、产品、运营和管理相关问题,请关注后留言。欢迎骚扰,不胜荣幸~

 

标签:自定义,Spring,void,public,处理器,登出,Security,response
From: https://www.cnblogs.com/xiangwang1111/p/16920329.html

相关文章

  • SpringBoot3整合MyBatis报错:Property ‘sqlSessionFactory‘ or ‘sqlSessionTemplate
    遇到了一个SpringBoot3整合MyBatis的问题,然后解决了。当然,这其实不是个大问题,只是自己编码时遇到了,然后总结总结分享一下。如果有遇到类似问题的,可以参考一下。交代......
  • Grafana+OpenSearch+Spring Boot集成(二) 【Grafana使用介绍一】
    Luence查询ElasticSearch/OpenSearchDataSource插件采用的是Luence查询,在创建的dashboard面板的query输入框中,可以设置查询条件对来自OpenSearch的数据进行筛选。Ter......
  • SpringBoot监控
    SpringBoot监控(了解)Actuator监控SpringBoot自带监控功能Actuator,可以帮助实现对程序内部运行情况监控,比如监控状况、Bean加载情况、配置属性、日志信息等。在第一天的sp......
  • Spring--注解开发+依赖注入
    自动装配数据层:业务层:自动装配:结果:若是将自动装配的注解放在set函数处:结果:结果相同,若是将set方法去掉的话:结果:这样的话,set方法也得到解放了耶!以上都是按照类型装......
  • Spring--bean管理(easy)
    bean作用范围利用同一个BookDao设置出来两个不同的对象,得到相同的地址:(默认为单例,即表现为同一个地址)要是想要得到不同的地址,就需要我们在接口实现类的上面加上这样一个......
  • Spring配置数据源
    //dataSource.javapackagespring_ioc_anno;importjava.beans.PropertyVetoException;importjava.sql.Connection;importjava.util.ResourceBundle;importjavax......
  • springboot整合jsp打包
    本文主要分享了对整合jsp的springboot项目打jar包,如何正确的配置maven pom。二、打包配置1.pom.xml添加spring-boot-maven-plugin配置<build><plugins>......
  • springboot整合jsp传参
    ViewController:packagecom.keafmd.controller;importorg.springframework.stereotype.Controller;importorg.springframework.ui.Model;importorg.springframewo......
  • Springboot应用中过滤器chain.doFilter后设置header无效
    本文是在使用过滤器添加动态header过程中遇到设置header无效,经过研究源码而产生。因为特殊需求,自定义的header必须在经过Controller处理之后,才能确定,所以不能在请求处理......
  • mongoDB的应用场景以及Spring和mongodb的整合
    mongoDB的应用场景​ mongodb是非关系型数据库,他的存储数据可以超过上亿条(老版本的mongodb有丢数据的情况,新版本不会有,网上说的),mongodb适合存储一些量大表关系较简单的数......