使用 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);
})
相关推荐
每次的天空18 分钟前
移动应用开发:自定义 View 处理大量数据的性能与交互优化方案
android·java·学习·交互
纪元A梦20 分钟前
贪心算法应用:最小反馈顶点集问题详解
java·算法·贪心算法
海盐泡泡龟1 小时前
ES6新增Set、Map两种数据结构、WeakMap、WeakSet举例说明详细。(含DeepSeek讲解)
前端·数据结构·es6
九转苍翎1 小时前
Java SE(10)——抽象类&接口
java
明月与玄武1 小时前
Spring Boot中的拦截器!
java·spring boot·后端
矢鱼1 小时前
单调栈模版型题目(3)
java·开发语言
n33(NK)1 小时前
Java中的内部类详解
java·开发语言
为美好的生活献上中指1 小时前
java每日精进 5.07【框架之数据权限】
java·开发语言·mysql·spring·spring cloud·数据权限
菲兹园长1 小时前
SpringBoot统一功能处理
java·spring boot·后端
一刀到底2111 小时前
spring ai alibaba 使用 SystemPromptTemplate 很方便的集成 系统提示词
spring·ai alibaba