欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > 项目集成Spring Security认证部分

项目集成Spring Security认证部分

2025/2/6 14:25:55 来源:https://blog.csdn.net/zzb1580/article/details/145413146  浏览:    关键词:项目集成Spring Security认证部分

一、需求分析

  在本项目中,使用了Spring Security框架来进行认证和授权管理。由于是前后端分离的项目,所有认证的请求需要通过Token来验证身份,系统中包括了用户登录、角色授权以及资源访问控制等功能。

系统中的资源控制:

  • 白名单url:指的是任何用户都可以访问的资源(例如登录、注册等公共接口),这些接口不需要身份验证。
  • 需要控制的资源:除了白名单中的接口,其他接口都需要进行权限验证。这些资源通常对应系统的菜单和按钮,用户根据所分配的角色和权限,决定是否能访问对应的接口。
  • 授权管理:通过角色和资源的绑定,确保只有授权的用户可以访问指定的接口,未授权的用户则返回403权限拒绝。

二、代码解读

SecurityConfig 配置

SecurityConfig类主要负责Spring Security的配置,其中包括了认证授权的管理。重点代码如下:

@Configuration
public class SecurityConfig {@Autowiredprivate JwtTokenAuthorizationManager jwtTokenAuthorizationManager;@Autowiredprivate SecurityConfigProperties securityConfigProperties;@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {List<String> ignoreUrl = securityConfigProperties.getIgnoreUrl();// 前后端分离,放行登录接口等白名单http.authorizeHttpRequests().antMatchers(ignoreUrl.toArray(new String[ignoreUrl.size()])).permitAll().anyRequest().access(jwtTokenAuthorizationManager);http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // 关闭sessionhttp.headers().cacheControl().disable(); // 关闭缓存http.csrf().disable(); // 禁用csrfreturn http.build();}
}
  • 白名单配置antMatchers方法用于配置哪些接口是公开的(如登录接口)。这些接口不需要Token验证。
  • 认证管理anyRequest().access(jwtTokenAuthorizationManager)表示其他所有接口都需要通过jwtTokenAuthorizationManager来进行Token认证。
  • 关闭Session:由于是无状态的认证方式,关闭了HTTP Session和缓存,确保每次请求都是独立的。
UserDetailsServiceImpl 实现

UserDetailsServiceImpl类负责加载用户信息,以供Spring Security进行认证。

@Service
public class UserDetailsServiceImpl implements UserDetailsService {@Autowiredprivate UserMapper userMapper;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {User user = userMapper.selectByUsername(username);if (ObjectUtil.isEmpty(user) || user.getDataState().equals("1")) {throw new RuntimeException("用户登录失败");}return BeanUtil.toBean(user, UserAuth.class);}
}
  • 通过loadUserByUsername方法,查询数据库中的用户信息,并将其封装为UserAuth对象返回给Spring Security,供认证过程使用。
LoginServiceImpl 认证过程

LoginServiceImpl类处理了用户的登录请求,并生成JWT Token。

@Override
public UserVo login(LoginDto loginDto) {UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(loginDto.getUsername(), loginDto.getPassword());Authentication authenticate = authenticationManager.authenticate(upat);if (!authenticate.isAuthenticated()) {throw new BaseException(BasicEnum.LOGIN_FAIL);}UserAuth userAuth = (UserAuth) authenticate.getPrincipal();UserVo userVo = BeanUtil.toBean(userAuth, UserVo.class);userVo.setPassword("");// 获取用户角色和资源,生成JWTList<Resource> resourceVoList = resourceMapper.findResourceVoListByUserId(userVo.getId());Set<String> resourceRequestPaths = resourceVoList.stream().map(Resource::getRequestPath).collect(Collectors.toSet());List<String> publicAccessUrls = securityConfigProperties.getPublicAccessUrls();resourceRequestPaths.addAll(publicAccessUrls);Map<String, Object> clamis = new HashMap<>();clamis.put("currentUser", JSONUtil.toJsonStr(userVo));String jwtToken = JwtUtil.createJWT(jwtTokenManagerProperties.getBase64EncodedSecretKey(), jwtTokenManagerProperties.getTtl(), clamis);userVo.setUserToken(jwtToken);// 存储访问权限到Redislong ttl = Long.valueOf(jwtTokenManagerProperties.getTtl() / 1000);String accessUrlsCacheKey = CacheConstants.ACCESS_URLS_CACHE + userVo.getId();redisTemplate.opsForValue().set(accessUrlsCacheKey, JSONUtil.toJsonStr(resourceRequestPaths), ttl, TimeUnit.SECONDS);return userVo;
}

1. 使用认证管理器进行认证

  • 用户通过提供的用户名和密码进行登录,系统首先创建UsernamePasswordAuthenticationToken对象,这个对象封装了用户的用户名和密码。
  • 然后,authenticationManager.authenticate(upat)方法会使用Spring Security的认证管理器来验证用户身份。如果认证失败,抛出自定义的BaseException,提示登录失败。

2. 获取用户数据

  • 当认证通过后,authenticate.getPrincipal()会返回包含用户信息的UserAuth对象。此对象包含了用户的基本信息(如用户名、密码等)。
  • 使用BeanUtil.toBean()方法将UserAuth对象转换为UserVo对象,便于后续的处理。

3. 获取用户资源权限列表

  • resourceMapper.findResourceVoListByUserId(userVo.getId())方法会查询数据库,获取当前用户拥有的资源权限,即用户可以访问的接口路径。
  • 这些路径将被存储在resourceRequestPaths集合中。

4. 合并公共访问的URL与用户资源路径

  • 系统还从配置文件中读取publicAccessUrls,即那些不需要认证的公共接口路径。
  • 将这些公共路径和用户可访问的资源路径合并,确保最终的访问列表包含了所有允许访问的接口。

5. 生成JWT Token

  • 使用JwtUtil.createJWT()方法创建一个JWT Token。这个Token包含了当前用户的信息(通过claims.put("currentUser", JSONUtil.toJsonStr(userVo))添加),并且设置了有效期(由jwtTokenManagerProperties.getTtl()控制)。
  • 生成的JWT Token被设置到userVo对象的userToken属性中,准备返回给前端。

6. 存储用户资源路径到Redis

  • 生成JWT Token后,系统会将用户可以访问的URL列表存储到Redis缓存中。这样做是为了提高性能,使得后续请求可以快速验证用户的权限。
  • 存储时设置了TTL(过期时间),使得权限数据与JWT Token的有效期一致。

7. 返回用户信息和JWT Token

  • 最终,系统返回一个UserVo对象,包含用户的基本信息和生成的JWT Token。前端可以使用这个Token进行后续的认证请求。
sql部分的编写:

​​​​​
<select id="selectByUserId" resultType="com.zzyl.entity.Resource">select sr.request_path requestPathfrom sys_user_role sur, sys_role_resource srr, sys_resource srwhere sur.role_id = srr.role_idand srr.resource_no = sr.resource_noand sr.resource_type = 'r'and sr.data_state = '0'and sur.user_id = #{userId}
</select>
  1. 表结构与关联

    • sys_user_role:该表将用户与角色关联起来。字段包括user_idrole_id,用于表示用户与角色的关系。
    • sys_role_resource:该表将角色与资源关联起来。字段包括role_idresource_no,用于表示角色与资源的关系。
    • sys_resource:该表包含了所有系统资源的详细信息。字段包括resource_norequest_path(资源路径)、resource_type等,用于存储系统中所有的资源信息。
  2. SQL查询过程

    • 通过sys_user_role表和sys_role_resource表的连接,获取当前用户(由sur.user_id表示)所拥有的所有角色。
    • 然后,通过sys_role_resource表和sys_resource表的连接,获取这些角色对应的资源路径。
    • 查询条件sr.resource_type = 'r'限定了只选择类型为“按钮”的记录,sr.data_state = '0'表示只选择状态为“有效”的资源。
  3. 查询结果

    • 查询的结果是该用户可以访问的所有资源的request_path(资源路径)。这些路径将用于后续的权限控制。

使用场景

  • 该SQL查询用于获取当前用户的权限数据。通过用户的user_id,系统可以查询到该用户所有角色对应的资源路径,并且只返回这些有效的资源路径(sr.data_state = '0'表示资源有效)。这些资源路径将会存储在urlList中,用于生成JWT Token时添加到Token的有效载荷中。

三、总结

  在Spring Security认证与授权集成中,主要分为用户登录认证、JWT Token生成与校验以及权限管理等部分。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com