You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用Spring Security通过Session属性校验用户登录状态

没问题,我来帮你实现这个Spring Security的集成需求,让除了/api/login之外的所有接口都自动校验登录状态,同时兼容你现有的Session存储用户信息的逻辑。咱们一步一步来:

1. 添加Spring Security依赖

首先得把Spring Security的依赖加到你的项目里,根据你用的构建工具选对应的配置:

Maven(pom.xml)

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Gradle(build.gradle)

implementation 'org.springframework.boot:spring-boot-starter-security'
2. 自定义Session认证过滤器

因为你是自己处理登录逻辑并把用户信息存在Session的USER_PROFILE键下,所以需要写一个自定义过滤器,让Spring Security能识别这个Session里的用户信息,认为用户已经完成认证。

创建一个SessionAuthenticationFilter类:

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class SessionAuthenticationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        HttpSession session = request.getSession(false); // 不自动创建新Session
        
        if (session != null) {
            // 从Session中获取用户信息
            Object userProfile = session.getAttribute("USER_PROFILE");
            
            if (userProfile != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                // 构造Authentication对象,这里可以根据你的UserProfile类调整权限信息
                // 如果你的UserProfile有角色/权限,记得把第二个参数换成对应的权限集合
                Authentication authentication = new UsernamePasswordAuthenticationToken(
                        userProfile,
                        null,
                        null // 示例:如果有普通用户权限,可换成 AuthorityUtils.createAuthorityList("ROLE_USER")
                );
                
                // 将认证信息存入SecurityContext,这样Spring Security就会认为用户已登录
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        
        filterChain.doFilter(request, response);
    }
}

这里要注意:如果你的USER_PROFILE对象包含用户的角色或权限信息,记得把第三个参数换成对应的权限集合,这样后续可以基于权限做更细粒度的接口控制。

3. 配置Spring Security安全规则

接下来创建Spring Security的配置类,定义哪些接口需要认证,把咱们的自定义过滤器加到过滤器链里:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                // 禁用CSRF(如果你的API是给前端调用的,可根据实际业务决定是否开启)
                .csrf().disable()
                // 配置请求权限规则
                .authorizeHttpRequests(auth -> auth
                        // 放行登录接口,允许匿名访问
                        .antMatchers("/api/login").permitAll()
                        // 其他所有接口都需要认证
                        .anyRequest().authenticated()
                )
                // 配置Session管理,沿用你自己的Session创建逻辑
                .sessionManagement(session -> session
                        .invalidSessionUrl("/api/login") // Session失效后跳转的地址,可根据需求调整
                )
                // 把自定义的Session认证过滤器加到官方认证过滤器之前
                .addFilterBefore(new SessionAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
        
        return http.build();
    }
}
4. 测试验证

现在你可以启动项目测试:

  • 直接调用除/api/login之外的接口,会返回401未认证;
  • 先调用/api/login完成登录(此时Session里会存入USER_PROFILE),再调用其他接口,就能正常访问了;
  • 当Session失效后,再次调用受保护的接口会回到未认证状态。

如果后续需要基于用户权限控制接口访问,只需要在自定义过滤器里调整Authentication对象的权限集合,Spring Security会自动帮你完成权限校验。


内容的提问来源于stack exchange,提问作者Frank

火山引擎 最新活动