使用 Spring Security的一些常用功能

在实际开发中,Spring Security 常常涉及一些常用的功能。以下是一些在开发中经常使用的 Spring Security 功能:

1. PasswordEncoder Bean(密码加密)

这段配置使用 BCryptPasswordEncoder 作为密码加密算法。它是 Spring Security 中常用的密码加密方式,通常用于存储和验证用户的密码。

java 复制代码
@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

2. 跨域配置(CORS)

配置跨域请求源、请求方法和请求头,允许前端应用跨域访问后端接口。该功能在前后端分离的应用中非常常见,尤其是需要不同域名访问同一服务时。

java 复制代码
@Bean
public CorsConfigurationSource configurationSource() {
    UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
    CorsConfiguration corsConfiguration = new CorsConfiguration();
    corsConfiguration.setAllowedOrigins(Arrays.asList("*"));
    corsConfiguration.setAllowedMethods(Arrays.asList("*"));
    corsConfiguration.setAllowedHeaders(Arrays.asList("*"));
    urlBasedCorsConfigurationSource.registerCorsConfiguration("/**",corsConfiguration);
    return urlBasedCorsConfigurationSource;
}

3. 自定义登录页面和失败处理

配置自定义的登录页面以及登录成功和失败时的处理逻辑。这是常见的安全性需求,尤其是在用户体验中需要提供定制的登录界面。

java 复制代码
.formLogin(formLogin -> {
    formLogin.loginProcessingUrl("/login")
             .successHandler(myAuthenticationSuccessHandler)
             .failureHandler(myAuthenticationFailHandler);
})

一般在登录成功的回调的处理器当中,我们会生成token并且存入Redis当中,在后续的拦截器当中从Redis获取token并且认证

4. 自定义登出处理

配置自定义的退出登录 URL 及退出成功后的处理。通常需要在登出成功后清理用户会话或进行其他操作。

java 复制代码
.logout(logout -> {
    logout.logoutUrl("/logout")
          .logoutSuccessHandler(myLogoutSuccessHandler);
})

5. 请求授权(授权控制)

配置不同的 URL 路径的访问权限,允许一些 URL 对所有用户开放(如登录页面、验证码等),并限制其他 URL 需要认证才能访问。

java 复制代码
.authorizeHttpRequests(authorizeHttpRequests -> {
    authorizeHttpRequests
        .requestMatchers("/toLogin", "/common/captcha").permitAll()
        .anyRequest().authenticated();
})

6. 禁用 CSRF(跨站请求伪造)保护

禁用 CSRF 防护,通常在使用无状态认证(如 JWT)时需要禁用 CSRF,因为它依赖于会话。

java 复制代码
.csrf(csrf -> {
    csrf.disable();
})

7. Session 管理

设置无状态的会话管理,即不创建会话,每次请求都需要进行身份认证。通常配合 JWT 使用。

java 复制代码
.sessionManagement(sessionManagement -> {
    sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
})

8. Token 过滤器

在 Spring Security 的过滤器链中加入自定义的 Token 过滤器(通常用于验证 JWT),确保每个请求都携带正确的认证信息。

对于 RESTful API 和前后端分离的应用,JWT 是一种常见的认证方式。Spring Security 可以与 JWT 配合使用来实现无状态认证。

你可以在 Spring Security 配置中添加一个 JWT 过滤器,拦截请求,提取 JWT 并进行认证。

示例:

java 复制代码
 // 在登录filter 之后添加一个token过滤器 确保退出登录的时候可以获取到认证信息
                .addFilterBefore(tokenFilter, LogoutFilter.class)

tokenFilter:

java 复制代码
@Component
public class TokenFilter  extends OncePerRequestFilter {


    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        response.setContentType("application/json;charset=UTF-8");

        // 获取请求路径
        String requestURI = request.getRequestURI();
        // 判断是否是登录请求 登录请求不需要验证
        if (requestURI.equals("/login")) {
            filterChain.doFilter(request, response);
        } else {
            // 取出请求头中的token
            String token = request.getHeader("token");
            // 判断token是否有内容
            if (!StringUtils.hasText(token)) {
                // 没有值
                R result = R.builder().code(901).msg("token不能为空").build();
                response.getWriter().write(JSONUtil.toJsonStr(result));
            } else {
                boolean verify = false;
                try {
                    // 验证通过了为true  这里需要捕获异常
                    verify = JWTUtil.verify(token, Constant.JWT_SECRET.getBytes());
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (!verify) {
                    // token无效
                    R result = R.builder().code(902).msg("token无效").build();
                    response.getWriter().write(JSONUtil.toJsonStr(result));
                } else {
                    JSONObject payload = JWTUtil.parseToken(token).getPayloads();
                    String userJson = payload.get("user", String.class);

                    TUser tUser = JSONUtil.toBean(userJson, TUser.class);
                    if (!token.equals(redisTemplate.opsForValue().get(Constant.REDIS_TOKEN_PREFIX + tUser.getId()))) {
                        R result = R.builder().code(903).msg("请求token错误").build();
                        response.getWriter().write(JSONUtil.toJsonStr(result));
                    } else {
                        // 验证通过了,要在Spring Security的上下文当中需要防止一个认证对象
                        // 这样的话 Spring Security 在执行后续的Filter的时候,才知道这个人是已经登录了的
                        UsernamePasswordAuthenticationToken authenticationToken
                                = new UsernamePasswordAuthenticationToken(tUser, null, tUser.getAuthorities());
                        SecurityContextHolder.getContext().setAuthentication(authenticationToken);

                        // 放行
                        filterChain.doFilter(request, response);
                    }
                }
            }
        }
    }
}

需要注意的是当验证通过了之后,需要设置Authentication 认证对象, UsernamePasswordAuthenticationToken 是其一个实现类。

9. 访问权限拒绝处理

配置权限不足时的处理逻辑,通常用来返回友好的错误信息或页面。

java 复制代码
.exceptionHandling(exceptionHandling -> {
    exceptionHandling.accessDeniedHandler(myAccessDeniedHandler);
})
相关推荐
敖云岚几秒前
【AI】SpringAI 第二弹:接入 DeepSeek 官方服务
java·人工智能·spring boot·后端·spring
purrrew4 分钟前
【数据结构_6】双向链表的实现
java·数据结构·链表
axinawang6 分钟前
Spring Boot管理Spring MVC
spring boot·spring·mvc
Danny_FD8 分钟前
前端BFC详解:从基础到深入的全面解读
前端
nangonghen10 分钟前
JAVA程序实现mysql读写分离并在kubernetes中演示
java·mysql·mybatis·读写分离
eternal__day15 分钟前
MyBatis-Plus 详解:快速上手到深入理解
java·spring boot·后端·spring·java-ee·maven·mybatis
临枫38817 分钟前
网页图像优化:现代格式与响应式技巧
前端
咪库咪库咪28 分钟前
构建交互网站
前端
Java中文社群28 分钟前
超实用!用FunctionCall实现快递AI助手
java·人工智能·后端
周星星日记29 分钟前
10.vue3中组件实现原理(上)
前端·vue.js·面试