This commit is contained in:
孙小云 2025-07-19 17:15:03 +08:00
parent 09bfe63b27
commit a856062a90
3 changed files with 125 additions and 14 deletions

View File

@ -5,11 +5,15 @@ import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
@ -49,6 +53,9 @@ import java.util.UUID;
@Configuration
public class SecurityConfig {
@Autowired
@Lazy
AuthenticationProvider tenantAwareAuthenticationProvider;
// 自定义认证入口点保留client_id参数
public static class CustomLoginUrlAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
public CustomLoginUrlAuthenticationEntryPoint(String loginFormUrl) {
@ -89,6 +96,7 @@ public class SecurityConfig {
@Bean
@Order(2)
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize ->
authorize
@ -115,22 +123,28 @@ public class SecurityConfig {
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID")
.permitAll()
);
)
// 添加会话管理配置
// .sessionManagement(session -> session
// .sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
// .maximumSessions(1) // 限制每个用户只能有一个会话
// )
// 添加自定义认证提供者
.authenticationProvider(tenantAwareAuthenticationProvider);
return http.build();
}
// 用户信息服务内存存储
@Bean
public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
UserDetails user = User.builder()
.username("user")
.password(passwordEncoder.encode("password"))
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
//
// // 用户信息服务内存存储
// @Bean
// public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
// UserDetails user = User.builder()
// .username("user")
// .password(passwordEncoder.encode("password"))
// .roles("USER")
// .build();
//
// return new InMemoryUserDetailsManager(user);
// }
// 注册客户端内存存储
@Bean

View File

@ -0,0 +1,62 @@
package com.tuoheng.oauth.oidc.provider;
import com.tuoheng.oauth.oidc.service.CustomUserDetailsService;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@Component
public class TenantAwareAuthenticationProvider implements AuthenticationProvider {
@Autowired
private CustomUserDetailsService userDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
// 获取请求中的额外参数
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.currentRequestAttributes()).getRequest();
String clientId = request.getParameter("client_id");
String tenantCode = request.getParameter("tenant-code");
System.out.println("=== 认证信息 ===");
System.out.println("用户名: " + username);
System.out.println("客户端ID: " + clientId);
System.out.println("租户代码: " + tenantCode);
// 执行标准的用户认证
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (userDetails != null && passwordEncoder.matches(password, userDetails.getPassword())) {
System.out.println("用户认证成功");
return new UsernamePasswordAuthenticationToken(
userDetails, password, userDetails.getAuthorities());
}
System.out.println("用户认证失败");
throw new BadCredentialsException("Invalid username or password");
}
@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
}

View File

@ -0,0 +1,35 @@
package com.tuoheng.oauth.oidc.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.HashSet;
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 创建UserDetails对象
return org.springframework.security.core.userdetails.User.builder()
.username("user")
.password(passwordEncoder.encode("password"))
.authorities(new HashSet<>())
.accountExpired(false)
.accountLocked(false)
.credentialsExpired(false)
.disabled(false)
.build();
}
}