我试图开发一个包含客户和供应商的系统,并发现了许多公共属性,所以我决定使用一个公共用户类,其中包含所有的身份验证信息。
类图:class digram
我一直有一个问题,当我把其中一个子类变成一个实体,以便Hibernate创建它们的表时,身份验证不起作用。
安全配置类:
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
@Bean
public AuthenticationManager authManager() {
var authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService());
authProvider.setPasswordEncoder(new BCryptPasswordEncoder());
return new ProviderManager(authProvider);
}
@Bean
public UserDetailsService userDetailsService() {
return new DatabaseUserDetailsService();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.cors(Customizer.withDefaults())
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests( auth -> auth
.requestMatchers("/token").permitAll()
.anyRequest().authenticated()
)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
.build();
}
}
字符串
令牌生成功能:
@Service
public class TokenService {
private final JwtEncoder encoder;
public TokenService(JwtEncoder encoder) {
this.encoder = encoder;
}
public String generateToken(Authentication authentication) {
Instant now = Instant.now();
String scope = authentication.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.joining(" "));
JwtClaimsSet claims = JwtClaimsSet.builder()
.issuer("self")
.issuedAt(now)
.expiresAt(now.plus(1, ChronoUnit.HOURS))
.subject(authentication.getName())
.claim("scope", scope)
.build();
return this.encoder.encode(JwtEncoderParameters.from(claims)).getTokenValue();
}
}
@PostMapping("/token")
public String token(@RequestBody LoginRequest userLogin) throws AuthenticationException {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userLogin.username(), userLogin.password());
Authentication authentication = authenticationManager.authenticate(token);
return tokenService.generateToken(authentication);
}
型
自定义用户详细信息服务:
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepo.findByUsername(username);
System.out.println(user + " " + username);
if(user == null){
throw new UsernameNotFoundException("User with username [" + username + "] not found in the system");
}
return new CustomUserDetails(user);
}
型
customUserDetails只是一个包含UserDetails的类,并有一个示例变量user,我们从中获取用户的数据。
用户类:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "user_table")
@Inheritance(strategy = InheritanceType.JOINED)
public class User{
@Id
private UUID user_id;
@Column(name = "username",unique = true,nullable = false)
private String username;
@Column(name = "password",nullable = false)
private String password;
}
型
客户类别:
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Entity(name = "customer") //when i remove this the jwt authentication works
public class Customer extends User{
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
}
型
我已经多次尝试调试令牌生成函数,结果出现了这个异常。dispatchException:第一个月
但我还没有找到任何导致此异常原因的资源
1条答案
按热度按时间xesrikrc1#
我通过让hibernate自动执行findByUsername(Stringusername)查询来解决这个问题,而不是使用带有本地查询的@Query进行查询