我们系统要做统一登录,授权服务器跳转到我们系统之后,进行账号校验存在的话,直接进入系统吗?如果直接进入系统,redis中的token又是怎样存进去的? 我想的是我们系统内部应该要再登录一次,然后登录的话,需要账号密码,但是拿不到密码.只能新写一个登录接口,只需要账号就能登录. 新写登录接口,还得用Spring Security原有的登录逻辑,原来的登录和新的登录需要并存,目前情况就是这样,有没有什么思路
在设计一个统一登录系统时,尤其是结合 Spring Security 和 Redis 来管理 token,有几个关键点需要注意。你提到的问题涉及到如何在用户经过授权服务器跳转到系统后,不需要再次输入密码就能直接登录并存储 token。以下是一些详细的思路和解决方案。
资源服务器负责保护资源,验证 token 的合法性。
使用 OAuth2/OpenID Connect:
资源服务器接收并解析这个 token,验证用户身份。
Spring Security 配置:
配置 OAuth2 授权服务器,生成并返回 JWT token。这部分的配置超出了当前问题的范围,可以参考 Spring Security OAuth2 的相关文档和教程。
配置 Spring Security 以处理 JWT token 的验证和用户身份的管理。
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/login").permitAll() .anyRequest().authenticated() .and() .oauth2ResourceServer() .jwt(); // 配置使用 JWT 验证 } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // 配置自定义用户细节服务 } }
在用户首次通过授权服务器登录成功后,解析 JWT token 并将其存储到 Redis 中。
@Service public class TokenService { @Autowired private RedisTemplate<String, String> redisTemplate; public void storeToken(String username, String token) { redisTemplate.opsForValue().set(username, token); // 设置 token 的过期时间,保持与 JWT token 的有效期一致 } public String getToken(String username) { return redisTemplate.opsForValue().get(username); } }
编写一个新的登录接口,只需要账号即可登录,并使用 Spring Security 的现有登录逻辑。
@RestController public class CustomLoginController { @Autowired private AuthenticationManager authenticationManager; @Autowired private TokenService tokenService; @PostMapping("/custom-login") public ResponseEntity<?> login(@RequestBody CustomLoginRequest request) { // 从请求中获取 JWT token String token = request.getToken(); // 解析 JWT token 并获取用户信息 String username = extractUsernameFromToken(token); // 创建一个 UsernamePasswordAuthenticationToken,只有用户名,没有密码 UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>()); // 使用 AuthenticationManager 进行身份验证 Authentication authentication = authenticationManager.authenticate(authenticationToken); SecurityContextHolder.getContext().setAuthentication(authentication); // 将 token 存储到 Redis 中 tokenService.storeToken(username, token); return ResponseEntity.ok("Login successful"); } private String extractUsernameFromToken(String token) { // 解析 JWT token 获取用户名的逻辑 // 使用 JWT 库,如 jjwt 或 Auth0 的 java-jwt } }
确保新的登录接口与现有的登录逻辑并存,可以通过不同的 URL 映射来实现。
@Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/login").permitAll() .antMatchers("/custom-login").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .defaultSuccessUrl("/home") .permitAll() .and() .logout() .permitAll() .and() .oauth2ResourceServer() .jwt(); }
通过以上步骤,你可以实现一个统一登录系统,用户在授权服务器成功认证后,无需再次输入密码即可登录到你的系统。你可以通过解析 JWT token 获取用户信息,并将 token 存储到 Redis 中进行管理。同时,保留原有的登录逻辑,以确保新旧登录方式的并存和兼容。