Java 使用数据库身份验证时,Spring Boot应用程序中的角色不起作用,但如果使用内存中的身份验证,则该角色起作用

Java 使用数据库身份验证时,Spring Boot应用程序中的角色不起作用,但如果使用内存中的身份验证,则该角色起作用,java,spring-boot,spring-security,Java,Spring Boot,Spring Security,我正在尝试在我的Spring Boot应用程序中设置安全角色 如果我使用内存中的用户,角色就会工作。我的代码如下所示: @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // add users for in memory authentication UserBuilder users = User.withDefaultPasswo

我正在尝试在我的Spring Boot应用程序中设置安全角色

如果我使用内存中的用户,角色就会工作。我的代码如下所示:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        
    // add users for in memory authentication
    UserBuilder users = User.withDefaultPasswordEncoder();
        
    auth.inMemoryAuthentication()
        .withUser(users.username("paul").password("test123").roles("MEMBER", "ADMIN"))
        .withUser(users.username("sandra").password("test123").roles("MEMBER", "ADMIN"))
        .withUser(users.username("matthew").password("test123").roles("MEMBER"));
}

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()
        .antMatchers("/users/list").hasAnyRole("MEMBER", "ADMIN")
        .antMatchers("/events/list").hasAnyRole("MEMBER", "ADMIN")
        .antMatchers("/events/showFormForAdd").hasRole("ADMIN")
        .antMatchers("/events/listEventAttendeeDetails*").hasRole("ADMIN")
        .antMatchers("/resources/**").permitAll()
        .and()
        .formLogin()
                .loginPage("/showMyLoginPage")
                .loginProcessingUrl("/authenticateTheUser")
                .permitAll();
    }
如果我对
configure()
使用数据库身份验证,则用户无权访问任何页面。我的数据库方法如下所示:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService);    
}
由于角色在内存中而不是数据库中工作,因此
configure(HttpSecurity http)
必须正常工作。我怀疑在获得我的角色方面存在一些问题。我的用户和权限(角色)模型如下:

@Entity
@Table(name="users")
public class User {
    
    public static final PasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder();
    
    @OneToMany(mappedBy="user",
            cascade={CascadeType.PERSIST, CascadeType.MERGE,
                    CascadeType.DETACH, CascadeType.REFRESH,
                    CascadeType.REMOVE})
    private List<Authority> authorities;

    // define fields
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id")
    private int id;

    @Column(name="first_name")
    private String firstName;

    @Column(name="last_name")
    private String lastName;
    
    @Column(name="gender")
    private String gender;
    
    @DateTimeFormat(pattern="yyyy-MM-dd")
    @Column(name="birth_date")
    private LocalDate birthDate;
    
    @Column(name="address_line1")
    private String addressLine1;
    
    @Column(name="address_line2")
    private String addressLine2;
    
    @Column(name="town")
    private String town;
    
    @Column(name="county")
    private String county;
    
    @Column(name="country")
    private String country;
    
    @Column(name="postcode")
    private String postcode;
    
    @Column(name="email")
    private String email;
    
    @Column(name="phone")
    private String phone;
    
    @Column(name="mobile")
    private String mobile;
    
    @Column(name="password")
    private @JsonIgnore String password;
    
    @Column(name="enabled")
    private int enabled;

    // define constructors
    public User() {
        
    }
    
    public User(List<Authority> authorities, int id, String firstName, String lastName, String gender, LocalDate birthDate,
        String addressLine1, String addressLine2, String town, String county, String country, String postcode,
        String email, String phone, String mobile, String password, int enabled) {
        this.authorities = authorities;
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.gender = gender;
        this.birthDate = birthDate;
        this.addressLine1 = addressLine1;
        this.addressLine2 = addressLine2;
        this.town = town;
        this.county = county;
        this.country = country;
        this.postcode = postcode;
        this.email = email;
        this.phone = phone;
        this.mobile = mobile;
        this.password = password;
        this.enabled = enabled;
    }
    
    public List<Authority> getAuthorities() {
        return authorities;
    }

    public void setAuthorities(List<Authority> authorities) {
        this.authorities = authorities;
    }
    
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public LocalDate getBirthDate() {
        return birthDate;
    }

    public void setBirthDate(LocalDate birthDate) {
        this.birthDate = birthDate;
    }

    public String getAddressLine1() {
        return addressLine1;
    }

    public void setAddressLine1(String addressLine1) {
        this.addressLine1 = addressLine1;
    }

    public String getAddressLine2() {
        return addressLine2;
    }

    public void setAddressLine2(String addressLine2) {
        this.addressLine2 = addressLine2;
    }

    public String getTown() {
        return town;
    }

    public void setTown(String town) {
        this.town = town;
    }

    public String getCounty() {
        return county;
    }

    public void setCounty(String county) {
        this.county = county;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getPostcode() {
        return postcode;
    }

    public void setPostcode(String postcode) {
        this.postcode = postcode;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = PASSWORD_ENCODER.encode(password);
    }

    public int getEnabled() {
        return enabled;
    }

    public void setEnabled(int enabled) {
        this.enabled = enabled;
    }
    
}


@Entity
@Table(name="authorities")
public class Authority {
    
    @ManyToOne(cascade= {CascadeType.PERSIST, CascadeType.MERGE,
            CascadeType.DETACH, CascadeType.REFRESH})
    @JoinColumn(name="email")
    private User user;
    
    @Id
    @Column(name="id")
    private String email;

    @Column(name="authority")
    private String authority;
    
    public Authority() {
        
    }

    public Authority(User user, String email, String authority) {
        this.user = user;
        this.email = email;
        this.authority = authority;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getAuthority() {
        return authority;
    }

    public void setAuthority(String authority) {
        this.authority = authority;
    }

}
INSERT INTO `authorities` 
VALUES 
('john','ROLE_MEMBER'),
('mary','ROLE_MEMBER'),
('mary','ROLE_MANAGER'),
('susan','ROLE_MEMBER'),
('susan','ROLE_ADMIN');
我在UserDetailsServiceImpl上做了一些日志记录。正如你所看到的,没有授权

2020-10-21 17:02:17.612  INFO 20363 --- [nio-8080-exec-4] c.p.clubmanager.aspect.LoggingAspect     : =====> in @Before: Calling method: UserDetailsServiceImpl.loadUserByUsername(..)
2020-10-21 17:02:17.613  INFO 20363 --- [nio-8080-exec-4] c.p.clubmanager.aspect.LoggingAspect     : =====> argument: Paul_carron@hotmail.com
2020-10-21 17:02:17.619  INFO 20363 --- [nio-8080-exec-4] c.p.clubmanager.aspect.LoggingAspect     : =====> in @AfterReturning: from method: UserDetailsServiceImpl.loadUserByUsername(..)
2020-10-21 17:02:17.619  INFO 20363 --- [nio-8080-exec-4] c.p.clubmanager.aspect.LoggingAspect     : =====> result: org.springframework.security.core.userdetails.User@eefb770b: Username: Paul_carron@hotmail.com; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; **Not granted any authorities**


在获取角色方面,我是否做错了什么,或者可能遗漏了什么?

UserDetailsServiceImpl
中,似乎您正在设置
roles/Authority
仅传递
new HashSet()
。您可以尝试以下方法:

try {
    Optional<User> optional = userRepository.findByEmail(username);
    List<SimpleGrantedAuthority> authorities =  set = new ArrayList<>();

    if(optional.isPresent()) {
    authorities = optional.get().getAuthorities().stream()
                                    .map(role -> new SimpleGrantedAuthority("ROLE_" + role.getName()))
                                    .collect(Collectors.toList()))
    }
    user = new org.springframework.security.core.userdetails.User(username, optional.get().getPassword(), authorities);
} catch (UsernameNotFoundException exception) {
    throw exception;
} catch (Exception exception) {
    throw new UsernameNotFoundException(username);
}
试试看{
可选=userRepository.findByEmail(用户名);
List authorities=set=new ArrayList();
if(可选的.isPresent()){
权限=可选。get().GetAuthories().stream()
.map(角色->新建SimpleGrantedAuthority(“角色”+role.getName())
.collect(收集器.toList())
}
user=new org.springframework.security.core.userdetails.user(用户名,可选.get().getPassword(),权限);
}捕获(UsernameNotFoundException异常){
抛出异常;
}捕获(异常){
抛出新用户名NotFoundException(用户名);
}

您是否可以使用UserDetailsServiceImpl查找您试图验证的用户,然后将其打印出来?当局是什么?它们是否前缀为ROLE_uu?如果不是,则它们需要符合您设置的授权规则。我在问题的底部添加了详细信息。您是否在实际代码中提供了权限?您的示例显示“根据需要添加SimpleGrantedAuthority to set”,但从未填充权限(set变量)。
try {
    Optional<User> optional = userRepository.findByEmail(username);
    List<SimpleGrantedAuthority> authorities =  set = new ArrayList<>();

    if(optional.isPresent()) {
    authorities = optional.get().getAuthorities().stream()
                                    .map(role -> new SimpleGrantedAuthority("ROLE_" + role.getName()))
                                    .collect(Collectors.toList()))
    }
    user = new org.springframework.security.core.userdetails.User(username, optional.get().getPassword(), authorities);
} catch (UsernameNotFoundException exception) {
    throw exception;
} catch (Exception exception) {
    throw new UsernameNotFoundException(username);
}