Spring Security 当User类在Spring中有实体子类时JWT身份验证失败

vsnjm48y  于 2023-08-05  发布在  Spring
关注(0)|答案(1)|浏览(95)

我试图开发一个包含客户和供应商的系统,并发现了许多公共属性,所以我决定使用一个公共用户类,其中包含所有的身份验证信息。
类图: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:第一个月
但我还没有找到任何导致此异常原因的资源

xesrikrc

xesrikrc1#

我通过让hibernate自动执行findByUsername(Stringusername)查询来解决这个问题,而不是使用带有本地查询的@Query进行查询

相关问题