diff --git a/oidc/src/main/java/com/tuoheng/oauth/oidc/config/SecurityConfig.java b/oidc/src/main/java/com/tuoheng/oauth/oidc/config/SecurityConfig.java index d88a450..1acb953 100644 --- a/oidc/src/main/java/com/tuoheng/oauth/oidc/config/SecurityConfig.java +++ b/oidc/src/main/java/com/tuoheng/oauth/oidc/config/SecurityConfig.java @@ -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 diff --git a/oidc/src/main/java/com/tuoheng/oauth/oidc/provider/TenantAwareAuthenticationProvider.java b/oidc/src/main/java/com/tuoheng/oauth/oidc/provider/TenantAwareAuthenticationProvider.java new file mode 100644 index 0000000..bb6b9b2 --- /dev/null +++ b/oidc/src/main/java/com/tuoheng/oauth/oidc/provider/TenantAwareAuthenticationProvider.java @@ -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); + } +} diff --git a/oidc/src/main/java/com/tuoheng/oauth/oidc/service/CustomUserDetailsService.java b/oidc/src/main/java/com/tuoheng/oauth/oidc/service/CustomUserDetailsService.java new file mode 100644 index 0000000..fe02ffb --- /dev/null +++ b/oidc/src/main/java/com/tuoheng/oauth/oidc/service/CustomUserDetailsService.java @@ -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(); + } + + +}