@Entity
@Table(name = "customers")
public class Customer extends User {
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "profile_id")
private Profile profile;
public Customer() {}
public Profile getProfile() {
return profile;
}
public void setProfile(Profile profile) {
this.profile = profile;
}
}
和雇员
admin面板auth:@Entity
@Table(name = "employees")
public class Employee extends User {
@NotNull
private EmployeeRole role;
public Employee() {
// new employee has the EMPLOYEE role by default
role = EmployeeRole.EMPLOYEE;
}
public EmployeeRole getRole() {
return role;
}
public void setRole(EmployeeRole role) {
this.role = role;
}
@Override
@Transient
public Collection<? extends GrantedAuthority> getAuthorities() {
return List.of(new SimpleGrantedAuthority(role.name()));
}
}
雇员可以具有
admin或雇员的角色。在这种情况下没关系。 Customer
没有任何角色。 用户实现userdetails.
我的配置是:
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
private final EmployeeService employeeService;
private final CustomerService customerService;
private final CorsConfigurationSource dashboardCorsConfigurationSource;
private final CorsConfigurationSource corsConfigurationSource;
public SecurityConfiguration(EmployeeService employeeService, CustomerService customerService,
@Qualifier("dashboard-cors-configuration-source")
CorsConfigurationSource dashboardCorsConfigurationSource,
@Qualifier("cors-configuration-source")
CorsConfigurationSource corsConfigurationSource) {
this.employeeService = employeeService;
this.customerService = customerService;
this.dashboardCorsConfigurationSource = dashboardCorsConfigurationSource;
this.corsConfigurationSource = corsConfigurationSource;
}
@Bean
@Order(0)
public SecurityFilterChain employeeSecurityFilterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity.securityMatcher("/api/employee/**")
.csrf(AbstractHttpConfigurer::disable)
.cors(httpSecurityCorsConfigurer ->
httpSecurityCorsConfigurer.configurationSource(dashboardCorsConfigurationSource)
)
.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry ->
authorizationManagerRequestMatcherRegistry.requestMatchers("/api/employee/auth/login")
.permitAll()
.anyRequest()
.authenticated()
)
.sessionManagement(httpSecuritySessionManagementConfigurer ->
httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.oauth2ResourceServer(httpSecurityOAuth2ResourceServerConfigurer ->
httpSecurityOAuth2ResourceServerConfigurer.jwt(Customizer.withDefaults())
)
.exceptionHandling(httpSecurityExceptionHandlingConfigurer ->
httpSecurityExceptionHandlingConfigurer
.authenticationEntryPoint(new BearerTokenAuthenticationEntryPoint())
.accessDeniedHandler(new BearerTokenAccessDeniedHandler())
)
//.userDetailsService(employeeService)
.headers(httpSecurityHeadersConfigurer -> httpSecurityHeadersConfigurer
.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin)
)
.build();
}
@Bean
@Order(2)
public SecurityFilterChain customerSecurityFilterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity.securityMatcher("/api/customer/**")
.csrf(AbstractHttpConfigurer::disable)
.cors(httpSecurityCorsConfigurer ->
httpSecurityCorsConfigurer.configurationSource(corsConfigurationSource))
.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry ->
authorizationManagerRequestMatcherRegistry.requestMatchers(
"/api/customer/register", "/api/customer/auth/login"
)
.permitAll()
.anyRequest()
.authenticated()
)
.sessionManagement(httpSecuritySessionManagementConfigurer ->
httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.oauth2ResourceServer(httpSecurityOAuth2ResourceServerConfigurer ->
httpSecurityOAuth2ResourceServerConfigurer.jwt(Customizer.withDefaults())
)
.exceptionHandling(httpSecurityExceptionHandlingConfigurer ->
httpSecurityExceptionHandlingConfigurer
.authenticationEntryPoint(new BearerTokenAuthenticationEntryPoint())
.accessDeniedHandler(new BearerTokenAccessDeniedHandler())
)
//.userDetailsService(customerService)
.headers(httpSecurityHeadersConfigurer -> httpSecurityHeadersConfigurer
.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin)
)
.build();
}
}
@Configuration
public class AuthenticationManagerConfiguration {
private final EmployeeService employeeService;
private final CustomerService customerService;
private final PasswordEncoder passwordEncoder;
public AuthenticationManagerConfiguration(EmployeeService employeeService, CustomerService customerService,
PasswordEncoder passwordEncoder) {
this.employeeService = employeeService;
this.customerService = customerService;
this.passwordEncoder = passwordEncoder;
}
@Bean
public AuthenticationManager authenticationManager() {
DaoAuthenticationProvider employeeDaoAuthenticationProvider = new DaoAuthenticationProvider();
employeeDaoAuthenticationProvider.setUserDetailsService(employeeService);
employeeDaoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
DaoAuthenticationProvider customerDaoAuthenticationProvider = new DaoAuthenticationProvider();
customerDaoAuthenticationProvider.setUserDetailsService(customerService);
customerDaoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
return new ProviderManager(employeeDaoAuthenticationProvider, customerDaoAuthenticationProvider);
}
}
@Service
public class AuthenticationService {
private final JwtEncoder jwtEncoder;
public AuthenticationService(JwtEncoder jwtEncoder) {
this.jwtEncoder = jwtEncoder;
}
public String getToken(Authentication authentication) {
User user = (User) authentication.getPrincipal();
List<String> roles = user.getAuthorities()
.stream()
.map(GrantedAuthority::getAuthority)
.toList();
Instant now = Instant.now();
JwtClaimsSet claimsSet = JwtClaimsSet.builder()
.issuer("e-commerce")
.issuedAt(now)
.expiresAt(now.plus(1, ChronoUnit.DAYS))
.subject(authentication.getName())
.claim("scope", roles)
.build();
return jwtEncoder.encode(JwtEncoderParameters.from(claimsSet))
.getTokenValue();
}
}
login端点正常工作,我得到令牌,但是解码时存在问题:
{
"iss": "e-commerce",
"sub": "[email protected]",
"exp": 1740480478,
"iat": 1740394078,
"scope": [
"ADMIN"
]
}
所有的东西都很好,并且有customer
代币:
{
"iss": "e-commerce",
"sub": "[email protected]",
"exp": 1740480575,
"iat": 1740394175,
"scope": [
"ADMIN" // why it is here?? It should be an empty array.
]
}
有问题。 Spring Boot使用错误的
AuthenticationProvider,并用错误的表格对我进行身份验证。我在这两个表中都有相同的电子邮件地址,因为我将逻辑分开,因此这些用户“不同”的用户除了具有相同的电子邮件之外。生活场景 - 您正在商店工作,因此您可以访问管理面板,但也可以私下下达订单。这就是为什么相同的电子邮件都有这种情况。
我也会得到警告Found 2 UserDetailsService beans, with names [customerService, employeeService]. Global Authentication Manager will not use a UserDetailsService for username/password login. Consider publishing a single UserDetailsService bean.
用户删除sservice并过滤两个表,因为这两个实体通过逻辑不同。我需要以某种方式指定正确的authenticationprovider可能。
我不想制作两个单独的服务器应用程序,因为刚刚复制和粘贴的代码将有很多相同的代码。这就是为什么我做多桌验证。应该对其进行审查
根据我收到的评论和春季文档,我可能找到了一个解决方案。 首先,我基于路径创建了一个:
AuthenticationManagerResolver<HttpServletRequest>
我不必在我的@Configuration
public class AuthenticationManagerConfiguration {
private final EmployeeService employeeService;
private final CustomerService customerService;
private final PasswordEncoder passwordEncoder;
public AuthenticationManagerConfiguration(EmployeeService employeeService, CustomerService customerService,
PasswordEncoder passwordEncoder) {
this.employeeService = employeeService;
this.customerService = customerService;
this.passwordEncoder = passwordEncoder;
}
private AuthenticationManager dashboardAuthenticationManager() {
DaoAuthenticationProvider employeeDaoAuthenticationProvider = new DaoAuthenticationProvider();
employeeDaoAuthenticationProvider.setUserDetailsService(employeeService);
employeeDaoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
return new ProviderManager(employeeDaoAuthenticationProvider);
}
private AuthenticationManager appAuthenticationManager() {
DaoAuthenticationProvider customerDaoAuthenticationProvider = new DaoAuthenticationProvider();
customerDaoAuthenticationProvider.setUserDetailsService(customerService);
customerDaoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
return new ProviderManager(customerDaoAuthenticationProvider);
}
@Bean
public AuthenticationManagerResolver<HttpServletRequest> pathAuthenticationManagerResolver() {
return (httpServletRequest) -> {
if (httpServletRequest.getRequestURI().startsWith("/api/app/")) {
return appAuthenticationManager();
} else if (httpServletRequest.getRequestURI().startsWith("/api/dashboard/")) {
return dashboardAuthenticationManager();
}
throw new OAuth2AuthenticationException("Invalid request");
};
}
}
中添加.oauth2ResourceServer(oauth2 -> oauth2.authenticationManagerResolver(pathAuthenticationManagerResolver()));
。除了我更改的URL之外,它与问题相同。没关系
当我添加时,我一直收到
SecurityFilterChain
。可能是因为我根本忽略了JWT,或者也许我必须在这种情况下添加一些过滤器。
我需要更改的最后一件事是在我的控制器中to
AuthenticationManager