spring-data-jpa Spring Security为没有任何角色的用户发送401未授权响应

dhxwm5r4  于 2022-11-10  发布在  Spring
关注(0)|答案(1)|浏览(143)

我是Spring Security的新手,我的Sping Boot 版本是2. 3. 11. RELEASE。
我使用MySQL作为数据库,使用SpringDataJPA来持久化实体。
我保存的用户没有任何角色。所以我不需要基于角色的身份验证。我只想验证输入的电子邮件和存储在我的数据库中的密码,但当我测试API时,Spring Security返回401“未授权”响应消息。
下面是我的代码片段。
用户类

@Entity
@ConfigurationProperties("user")
@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
@Table(name = "users")
public class User implements Serializable, UserDetails {

    @Id
    private String id;

    @NotBlank
    private String name;

    @Column(name = "phone_ext")
    private String phoneExt;

    @Column(name = "phone_no")
    private String phoneNo;

    @NotNull
    private String email;

    @NotNull
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "country")
    private Country country;

    @NotNull
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "currency")
    private Currency currency;

    @Column(name = "fb_id")
    private String facebookId;

    @Column(name = "google_id")
    private String googleId;

    @NotNull
    @Column(name = "current_balance")
    private int currentBalance;

    @NotNull
    @Column(name = "is_enabled")
    private boolean enabled;

    @NotNull
    @Column(name = "free_sample_used")
    private boolean isfreeSampleUsed;

    @Column(name = "client_id")
    private String clientId;

    @JsonIgnore
    @Column(name = "password", nullable = true)
    private String password;

    @Column(name = "coupons_used")
    private String couponsUsed;

    /**
     * @return the userId
     */
    public String getId() {
        return id;
    }

    /**
     * @param userId the userId to set
     */
    public User setId(String userId) {
        this.id = userId;
        return this;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public User setName(String name) {
        this.name = name;
        return this;
    }

    /**
     * @return the phoneExt
     */
    public String getPhoneExt() {
        return phoneExt;
    }

    /**
     * @param phoneExt the phoneExt to set
     */
    public User setPhoneExt(String phoneExt) {
        this.phoneExt = phoneExt;
        return this;
    }

    /**
     * @return the phoneNo
     */
    public String getPhoneNo() {
        return phoneNo;
    }

    /**
     * @param phoneNo the phoneNo to set
     */
    public User setPhoneNo(String phoneNo) {
        this.phoneNo = phoneNo;
        return this;
    }

    /**
     * @return the email
     */
    public String getEmail() {
        return email;
    }

    /**
     * @param email the email to set
     */
    public User setEmail(String email) {
        this.email = email;
        return this;
    }

    /**
     * @return the country
     */
    public Country getCountry() {
        return country;
    }

    /**
     * @param country the country to set
     */
    public User setCountry(Country country) {
        this.country = country;
        return this;
    }

    /**
     * @return the currency
     */
    public Currency getCurrency() {
        return currency;
    }

    /**
     * @param currency the currency to set
     */
    public User setCurrency(Currency currency) {
        this.currency = currency;
        return this;
    }

    /**
     * @return the facebookId
     */
    public String getFacebookId() {
        return facebookId;
    }

    /**
     * @param facebookId the facebookId to set
     */
    public User setFacebookId(String facebookId) {
        this.facebookId = facebookId;
        return this;
    }

    /**
     * @return the googleId
     */
    public String getGoogleId() {
        return googleId;
    }

    /**
     * @param googleId the googleId to set
     */
    public User setGoogleId(String googleId) {
        this.googleId = googleId;
        return this;
    }

    /**
     * @return the currentBalance
     */
    public int getCurrentBalance() {
        return currentBalance;
    }

    /**
     * @param currentBalance the currentBalance to set
     */
    public User setCurrentBalance(int currentBalance) {
        this.currentBalance = currentBalance;
        return this;
    }

    /**
     * @return the isEnabled
     */
    public boolean isEnabled() {
        return enabled;
    }

    /**
     * @param isEnabled the isEnabled to set
     */
    public User setEnabled(boolean enabled) {
        this.enabled = enabled;
        return this;
    }

    /**
     * @return the isfreeSampleUsed
     */
    public boolean isIsfreeSampleUsed() {
        return isfreeSampleUsed;
    }

    /**
     * @param isfreeSampleUsed the isfreeSampleUsed to set
     */
    public User setIsfreeSampleUsed(boolean isfreeSampleUsed) {
        this.isfreeSampleUsed = isfreeSampleUsed;
        return this;
    }

    /**
     * @return the clientId
     */
    public String getClientId() {
        return clientId;
    }

    /**
     * @param clientId the clientId to set
     */
    public User setClientId(String clientId) {
        this.clientId = clientId;
        return this;
    }

    /**
     * @param password the password to set
     */
    public User setPassword(String password) {
        this.password = password;
        return this;
    }

    /**
     * @return the password
     */
    @Override
    public String getPassword() {
        return this.password;
    }

    @Override
    public String getUsername() {
        return this.email;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return new HashSet<GrantedAuthority>();
    }
    @Override
    public boolean isAccountNonExpired() {
        return false;
    }

    @Override
    public boolean isAccountNonLocked() {
        return false;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return false;
    }

    /**
     * @return the couponsUsed
     */
    public String getCouponsUsed() {
        return couponsUsed;
    }

    /**
     * @param couponsUsed the couponsUsed to set
     */
    public void setCouponsUsed(String couponsUsed) {
        this.couponsUsed = couponsUsed;
    }

    public User() {
        super();
        this.id = null ;
        this.name = "";
        this.email = "";
        this.country = new Country();
        this.currency = new Currency();
        this.currentBalance = 0;
        this.enabled = true;
        this.isfreeSampleUsed = false;
        this.password = "";
    }

    /**
     * To generate invoice id
     *
     * @return random UUID
     */
    public String generateId() {
        return UUID.randomUUID().toString();
    }

}

控制器中的API端点

@PostMapping("/authenticate")
    public ResponseEntity<IECAuthenticationResponse> createAuthenticationToken(@RequestBody IECAuthenticationRequestBody body,
                                                                              @NotNull @RequestParam (value = "client_id", required = true)
                                                                               String clientId){
        IECAuthenticationResponse iecAuthenticationResponse = new IECAuthenticationResponse();
        try {
            boolean valid = EmailValidator.getInstance().isValid(body.getEmail());
            if(!valid){
                throw new PaperTrueInvalidEmailException("Invalid email address, please use a valid email address");
            }
            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(body.getEmail(), body.getPassword()));
            UserDetails userDetails = myUserDetailsServices.loadUserByUsername(body.getEmail());
            System.out.println("User Details username ----> " + userDetails.getUsername());
            System.out.println("User Details Password ---> " + userDetails.getPassword());
            User user = userService.getUserByEmail(body.getEmail());
            if(!user.getClientId().equals(clientId)) {
                throw new PaperTrueInvalidClientException("Invalid clientId, Please check the clientId");
            }
            boolean matches = passwordEncoder.matches(body.getPassword(), user.getPassword());
            System.out.println("Matches --> " + matches);
            if(matches) {
                String token = jwtUtil.generateToken(userDetails);
                iecAuthenticationResponse.setToken(token)
                        .setUserId(user.getId())
                        .setStatus(new Status("User authenticated successfully"));
            }
        } catch (PaperTrueUserNotFoundException | PaperTrueInvalidEmailException | PaperTrueInvalidClientException e) {
            iecAuthenticationResponse.setStatus(new Status(e.getCode(), e.getMessage()));
        }catch (BadCredentialsException e){
            iecAuthenticationResponse.setStatus(new Status(e.getMessage()));
        }
        return ResponseEntity.ok(iecAuthenticationResponse);

我的用户详细信息服务类

@Service
public class MyUserDetailsServices implements UserDetailsService {

    @Autowired
    private UserService userService;

    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        System.out.println("Inside loadByUserName function ------");
        User emailInstance = null;
        try {
            System.out.println("------ Inside try block-------");
            emailInstance = userService.getEmailInstance(email);
            System.out.println("Email Instance ----> " + emailInstance);
        } catch (PaperTrueUserNotFoundException e) {
            emailInstance = null;
        }
       if(emailInstance == null){
           throw new UsernameNotFoundException("User not found w.r.t given email");
       }
        System.out.println("Email ---> " + emailInstance.getEmail());
        System.out.println("Password ---> " + emailInstance.getPassword());
        return emailInstance;
    }
}

安全配置类

@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private JwtAuthenticationEntryPoint unauthorizedHandler;

    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;

    @Autowired
    private MyUserDetailsServices myUserDetailsServices;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedHeaders(
                List.of("Authorization", "Cache-Control", "Content-Type", "X-PT-SESSION-ID", "NGSW-BYPASS"));
        corsConfiguration.setAllowedOrigins(List.of("*"));
        corsConfiguration
                .setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PUT", "OPTIONS", "PATCH", "DELETE"));
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.setExposedHeaders(List.of("Authorization"));

        http.csrf().disable()
                .authorizeRequests()
                 .antMatchers("/iec/register", "/iec/authenticate").permitAll()
                .anyRequest().authenticated().and()
                .cors().configurationSource(request -> corsConfiguration)
                .and().exceptionHandling().authenticationEntryPoint(unauthorizedHandler)
                .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailsServices).passwordEncoder(encoder());
    }
    @Bean
    public PasswordEncoder encoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        // configure AuthenticationManager so that it knows from where to load
        // user for matching credentials
        // Use BCryptPasswordEncoder
        auth.userDetailsService(myUserDetailsServices).passwordEncoder(encoder());
    }

}
JwtAuthentication类别

@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authenticationException) throws IOException, ServletException {
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized 1");
    }
}

JwtAuthenticationFilter类别

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private MyUserDetailsServices userDetailsService;

    @Autowired
    private JwtUtil jwtUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String header = request.getHeader("Authorization");
        String userName = null;
        String token = null;
        if(header != null && header.startsWith("Bearer ")){
            token = header.substring(7);
            try {
                userName = jwtUtil.extractUsername(token);
            } catch (IllegalArgumentException e){
                System.out.println("Unable to get JWT token.");
            } catch (ExpiredJwtException e){
                System.out.println("JWT Token has expired.");
            } catch (SignatureException e){
                System.out.println("Authentication Failed. Username or Password not valid.");
            }
        }  else {
            logger.warn("Couldn't find bearer string, will ignore the header");
        }

        if(userName != null && SecurityContextHolder.getContext().getAuthentication() == null){
            UserDetails userDetails = userDetailsService.loadUserByUsername(userName);
            if(jwtUtil.validateToken(token, userDetails)){
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                        new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

                usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }
        filterChain.doFilter(request, response);
    }
}

请帮助我在这一点上,如果在情况下,我做任何不正确的

7lrncoxx

7lrncoxx1#

通过更改UserEntity中UserDetails接口的三个覆盖方法的布尔值解决了该问题。

@Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

之前的值为false。将其更改为true后,该值生效!

相关问题