使用 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);
})
相关推荐
大刀爱敲代码11 分钟前
基础算法01——二分查找(Binary Search)
java·算法
大土豆的bug记录1 小时前
鸿蒙进行视频上传,使用 request.uploadFile方法
开发语言·前端·华为·arkts·鸿蒙·arkui
maybe02091 小时前
前端表格数据导出Excel文件方法,列自适应宽度、增加合计、自定义文件名称
前端·javascript·excel·js·大前端
HBR666_1 小时前
菜单(路由)权限&按钮权限&路由进度条
前端·vue
A-Kamen2 小时前
深入理解 HTML5 Web Workers:提升网页性能的关键技术解析
前端·html·html5
追风少年1552 小时前
常见中间件漏洞之一 ----【Tomcat】
java·中间件·tomcat
yang_love10113 小时前
Spring Boot 中的 @ConditionalOnBean 注解详解
java·spring boot·后端
郑州吴彦祖7723 小时前
【Java】UDP网络编程:无连接通信到Socket实战
java·网络·udp
锋小张3 小时前
a-date-picker 格式化日期格式 YYYY-MM-DD HH:mm:ss
前端·javascript·vue.js
spencer_tseng4 小时前
eclipse [jvm memory monitor] SHOW_MEMORY_MONITOR=true
java·jvm·eclipse