SpringSecurity整合springBoot、redis token动态url权限校验

本文介绍了如何使用Spring Security实现自定义登录认证,包括登录过滤器、认证管理器、成功和失败处理类的创建。同时,详细阐述了基于FilterSecurityInterceptor的接口权限校验,包括自定义的权限元数据源和决策管理器,以及处理匿名用户和已登录用户无权限访问资源的异常处理。整个过程旨在提供灵活的权限控制,并确保系统安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

简单先说一下需求吧,这样也好让看的人知道到底适不适合自己。
1、实现自定义的登录认证。
2、登录成功,生成token并将token 交由redis管理。
3、登录后对用户访问的接口进行接口级别权限认证。

springSecurity提供的注解权限校验适合的场景是系统中仅有固定的几个角色,且角色的凭证不可修改(如果修改需要改动代码)。

@PreAuthorize("hasAuthority('ROLE_TELLER')") 
public	Account	post(Account account, double amount); 

注:ROLE_TELLER是写死的。
后端系统的访问请求有以下几种类型:
1、登录、登出(可自定义url)
2、匿名用户可访问的接口(静态资源,demo示例等)
3、其他接口(在登录的前提下,继续判断访问者是否有权限访问)

环境搭建

依赖引入,包括springSecurity、redis、redis session需要的依赖:

<!--springSecurity安全框架-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>2.3.4.RELEASE</version>
</dependency>
<!-- 默认通过SESSIONId改为通过请求头与redis配合验证session -->
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
    <version>2.3.1.RELEASE</version>
</dependency>
<!--redis支持-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.3.4.RELEASE</version>
</dependency>

注:springBoot版本也是2.3.4.RELEASE,如果有版本对应问题,自行解决。有用到swagger,为了便于测试。

新建springSecurity配置类

新建 WebSecurityConfig.java 继承自 WebSecurityConfigurerAdapter,过滤匿名用户可访问的接口。
WebSecurityConfig作为springSecurity的主配置文件。

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
   
    
    /**
     * Swagger等静态资源不进行拦截
     */
    @Override
    public void configure(WebSecurity web) {
   
        web.ignoring().antMatchers(
                "/*.html",
                "/favicon.ico",
                "/**/*.html",
                "/**/*.css",
                "/**/*.js",
                "/error",
                "/webjars/**",
                "/resources/**",
                "/swagger-ui.html",
                "/swagger-resources/**",
                "/v2/api-docs");
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
   
        http.authorizeRequests()
                //配置一些不需要登录就可以访问的接口
                .antMatchers("/demo/**", "/about/**").permitAll()
                //任何尚未匹配的URL只需要用户进行身份验证
                .anyRequest().authenticated()
                .and()
                .formLogin()//允许用户进行基于表单的认证
                .loginPage("/mylogin");
    }

}

在这里插入图片描述
注:证明可以访问静态资源不会被拦截

自定义登录认证

springSecurity是基于过滤器进行安全认证的。
我们需要自定义:
1、登录过滤器:负责过滤登录请求,再交由自定义的登录认证管理器处理。
2、登录成功处理类:顾名思义,登录成功后的一些处理(设置返回信息提示“登录成功!”,返回数据类型为json)。
3、登录失败处理类:类似登录成功处理类。Ps:登录成功处理类和失败处理类有默认的实现可以不自定义。但是建议自定义,因为返回的信息为英文,一般情况不符合要求。
4、登录认证管理器:根据过滤器传过来的登录参数,进行登录认证,认证后授权。

新建登录成功处理类

需要实现 AuthenticationSuccessHandler

@Component
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
   

    private static final Logger LOGGER = LoggerFactory.getLogger(CustomAuthenticationSuccessHandler.class);

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
   
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
        //登录成功返回的认证体,具体格式在后面的登录认证管理器中
        String responseJson = JackJsonUtil.object2String(ResponseFactory.success(authentication));
        if (LOGGER.isDebugEnabled()) {
   
            LOGGER.debug("登录成功!");
        }
        response.getWriter().write(responseJson);
    }
}

新建登录失败处理类

实现AuthenticationFailureHandler

@Component
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {
   

    private static final Logger LOGGER = LoggerFactory.getLogger(CustomAuthenticationFailureHandler.class);

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException {
   
        String errorMsg;
        if (StringUtils.isNotBlank(e.getMessage())) {
   
            errorMsg = e.getMessage();
        } else {
   
            errorMsg = CodeMsgEnum.LOG_IN_FAIL.getMsg();
        }
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
        String responseJson = JackJsonUtil.object2String(ResponseFactory.fail(CodeMsgEnum.LOG_IN_FAIL,errorMsg));
        if (LOGGER.isDebugEnabled()) {
   
            LOGGER.debug("认证失败!");
        }
        response.getWriter().write(responseJson);
    }

}
新建登录认证管理器

实现 AuthenticationProvider ,负责具体的身份认证(一般数据库认证,在登录过滤器过滤掉请求后传入)

@Component
public class UserVerifyAuthenticationProvider implements AuthenticationProvider {
   

    private PasswordEncoder passwordEncoder;
    @Autowired
    private UserService userService;
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
   
        String userName = (String) authentication.getPrincipal(); // Principal 主体,一般指用户名
        String passWord = (String) authentication.getCredentials(); //Credentials 网络凭证,一般指密码
        //通过账号去数据库查询用户以及用户拥有的角色信息
        UserRoleVo userRoleVo = userService.findUserRoleByAccount(userName);
        //数据库密码
        String encodedPassword = userRoleVo.getPassWord();
        
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值