当前位置: 首页 > news >正文

Spring AI Alibaba 基于JWT的鉴权登录系统实现详解

文章目录

  • Spring AI Alibaba 基于JWT的鉴权登录系统实现详解
    • 一、系统架构概述
    • 二、核心组件分析
      • 1. 用户实体设计
      • 2. 角色和权限管理
      • 3. Spring Security配置
    • 三、JWT认证机制实现
      • 1. JWT令牌工具类
      • 2. JWT认证过滤器
    • 四、用户认证流程
      • 1. 登录处理
      • 2. 用户详情加载服务
    • 五、总结

Spring AI Alibaba 基于JWT的鉴权登录系统实现详解

采用了基于JWT(JSON Web Token)的无状态认证方案,实现了灵活、安全的用户登录和权限管理。本文将深入分析其实现机制。

一、系统架构概述

认证系统基于Spring Security框架构建,采用了以下核心组件:

  • Spring Security:提供基础的认证和授权功能
  • JWT:实现无状态的令牌认证
  • Spring Data JPA:处理用户和角色数据的持久化
  • BCrypt:进行密码加密和验证

二、核心组件分析

1. 用户实体设计

User实体类实现了Spring Security的UserDetails接口,使其成为认证系统的核心:

@Data
@Entity
@Table(name = "users")
public class User implements UserDetails {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(name = "username", nullable = false, unique = true, length = 50)private String username;@Column(name = "password", nullable = false, length = 255)private String password;@Column(name = "email", nullable = false, unique = true, length = 100)private String email;@Column(name = "enabled", nullable = false)private boolean enabled = true;@Column(name = "Status", nullable = false)private Integer Status ;@ManyToMany(fetch = FetchType.EAGER)@JoinTable(name = "user_roles",joinColumns = @JoinColumn(name = "user_id"),inverseJoinColumns = @JoinColumn(name = "role_id"))private Set<Role> roles = new HashSet<>();// 实现UserDetails接口的其他方法
}

2. 角色和权限管理

Role实体实现了GrantedAuthority接口,用于定义用户权限:

@Data
@Entity
@Table(name = "roles")
public class Role implements GrantedAuthority {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(name = "name", nullable = false, unique = true, length = 50)private String name;@Overridepublic String getAuthority() {// 确保角色名称以ROLE_前缀开始if (name != null && !name.startsWith("ROLE_")) {return "ROLE_" + name;}return name;}
}

3. Spring Security配置

SecurityConfig类是整个认证系统的核心配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig {@Autowiredprivate UserDetailsService userDetailsService;@Autowiredprivate JwtAuthenticationFilter jwtAuthenticationFilter;@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Beanpublic AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {return authConfig.getAuthenticationManager();}@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.csrf(csrf -> csrf.disable()) // 禁用CSRF保护(适用于API).authorizeHttpRequests(auth -> auth// 允许匿名访问的端点.requestMatchers("/api/auth/register", "/api/auth/login", "/error").permitAll()// 允许匿名访问静态资源.requestMatchers("/", "/index.html", "/login.html", "/register.html", "/chat.html", "/static/**", "/css/**", "/js/**", "/img/**", "/favicon.ico").permitAll()// 所有其他请求需要认证.anyRequest().authenticated())// 配置无状态会话.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))// 添加JWT认证过滤器.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);return http.build();}
}

三、JWT认证机制实现

1. JWT令牌工具类

JwtTokenUtil类负责JWT令牌的生成、解析和验证:

@Component
public class JwtTokenUtil {private static final Logger logger = LoggerFactory.getLogger(JwtTokenUtil.class);@Value("${jwt.secret}")private String jwtSecret;@Value("${jwt.expiration}")private long jwtExpiration;// 创建签名密钥private Key getSigningKey() {byte[] keyBytes = jwtSecret.getBytes(StandardCharsets.UTF_8);return new SecretKeySpec(keyBytes, SignatureAlgorithm.HS512.getJcaName());}// 生成JWT令牌public String generateToken(String username) {Date now = new Date();Date expiryDate = new Date(now.getTime() + jwtExpiration);return Jwts.builder().setSubject(username).setIssuedAt(now).setExpiration(expiryDate).signWith(getSigningKey(), SignatureAlgorithm.HS256).compact();}// 从令牌中获取用户名public String getUsernameFromToken(String token) {Claims claims = Jwts.parserBuilder().setSigningKey(getSigningKey()).build().parseClaimsJws(token).getBody();return claims.getSubject();}// 验证令牌public boolean validateToken(String token, UserDetails userDetails) {String username = getUsernameFromToken(token);return username.equals(userDetails.getUsername()) && !isTokenExpired(token);}
}

2. JWT认证过滤器

JwtAuthenticationFilter是一个拦截器,负责从请求头中提取JWT令牌并验证:

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {@Autowiredprivate JwtTokenUtil jwtTokenUtil;@Autowiredprivate UserDetailsServiceImpl userDetailsService;@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {try {// 获取Authorization头String header = request.getHeader("Authorization");String username = null;String jwt = null;// 检查Authorization头格式if (header != null && header.startsWith("Bearer ")) {jwt = header.substring(7);username = jwtTokenUtil.getUsernameFromToken(jwt);}// 验证令牌并设置认证信息if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {UserDetails userDetails = userDetailsService.loadUserByUsername(username);if (jwtTokenUtil.validateToken(jwt, userDetails)) {UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));SecurityContextHolder.getContext().setAuthentication(authentication);}}} catch (Exception e) {logger.error("无法设置用户认证: {}", e);}filterChain.doFilter(request, response);}
}

四、用户认证流程

1. 登录处理

AuthController中的登录方法处理用户认证请求:

@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody UserLoginDTO loginDTO) {try {// 1. 创建认证请求对象UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginDTO.getUsername(),loginDTO.getPassword());// 2. 执行身份验证Authentication authentication = authenticationManager.authenticate(authenticationToken);// 3. 设置认证信息到安全上下文SecurityContextHolder.getContext().setAuthentication(authentication);// 4. 生成JWT令牌String token = jwtTokenUtil.generateToken(authentication.getName());// 5. 返回登录成功响应Map<String, Object> successResponse = new HashMap<>();successResponse.put("success", true);successResponse.put("message", "登录成功");successResponse.put("token", token);successResponse.put("username", authentication.getName());return ResponseEntity.ok(successResponse);} catch (BadCredentialsException e) {// 处理密码错误return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("用户名或密码错误");} catch (AuthenticationException e) {// 处理其他认证异常return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("身份验证错误");}
}

2. 用户详情加载服务

UserDetailsServiceImpl负责从数据库加载用户信息:

@Service
public class UserDetailsServiceImpl implements UserDetailsService {@Autowiredprivate UserRepository userRepository;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 从数据库中查找用户User user = userRepository.findByUsername(username).orElseThrow(() -> new UsernameNotFoundException("用户不存在: " + username));// 直接返回User实体,因为它已经实现了UserDetails接口return user;}
}

五、总结

基于JWT的认证方案,结合了Spring Security的强大功能和JWT的灵活特性,实现了一个安全、可扩展的用户认证系统。该方案具有以下优势:

  • 无状态性:服务器不需要存储会话信息,便于水平扩展
  • 跨域支持:JWT可以在不同域之间安全传输
  • 前后端分离友好:适合现代前后端分离的Web应用架构
  • 安全性高:通过签名和加密保障令牌安全
http://www.dtcms.com/a/537278.html

相关文章:

  • 软件测试(五)--自动化测试Selenium(一)
  • 网站项目开发网站菜单导航制作教程
  • 兰州最好的网站建设公司青岛网站优化排名
  • 某汽车公司4S店携手Acrel-5000建筑能耗管理系统,实现连锁门店能源精细化管理新突破
  • LeetCode 刷题【135. 分发糖果】
  • 专业做网站建设的网站内页产品 首页推荐
  • TCP 流通信中的 EOFException 与 JSON 半包问题解析
  • Garnet技术深度解析:微软研究院出品的高性能缓存存储引擎
  • 如何制作论坛网站网页制作软件是哪个
  • 《从点击到响应:HTTP 请求是如何传出去的》
  • 科技+文化:从“参观游览”到“沉浸共生”的文旅产业革命
  • 做条形图的网站河南郑州网站建设
  • 青少儿机器人技术学什么?
  • 基本魔法语言数组 (一) (C语言)
  • php源码网站修改保定建设厅网站
  • 网站建设访问对象网站开发毕设的需求分析
  • 【实战】自然语言处理--长文本分类(2)BERTSplitLSTM算法
  • Markdown模板20251027
  • Linux命令解释:cp -r --parents用法
  • 关于企业的网站天津做网站找谁
  • 0138. 随机链表的复制
  • 长春网站建设公司seo是什么意思教程
  • 【vllm】源码解读:vLLM 中 Data Parallelism DP=8 核心原理详解
  • 对信号的理解
  • 【系统分析师】高分论文:论软件的安全性设计(某校通系统)
  • 硬盘专业名词:总线、协议、接口详细解析
  • Agent Skills应用解析:构建可扩展、高效率AI探员
  • 【车载测试常见问题】CAN一致性测试包含哪些内容?
  • 成都网站开发制作上海进博会
  • 云手机和虚拟机的区别都有哪些?