Spring Security 403错误尽管CSRF已禁用

huangapple go评论71阅读模式
英文:

Spring security 403 error despite CSRF disabled

问题

以下是要翻译的部分:

我有一组规则,规定了哪些角色可以访问哪些网址。然而,在角色应该可以访问的网址上,我却收到了403错误。请参考以下的代码和问题。

日志:

org.springframework.security.access.AccessDeniedException: 访问被拒绝
at
org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84)
~[spring-security-core-5.3.3.RELEASE.jar:5.3.3.RELEASE] at
org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233)
~[spring-security-core-5.3.3.RELEASE.jar:5.3.3.RELEASE] at
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:123)
~[spring-security-web-5.3.3.RELEASE.jar:5.3.3.RELEASE]

Spring安全配置。注意,admin/** 允许管理员使用。我已使用管理员身份登录,访问admin/welcome,但收到了403错误。

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    
    // 访问嵌入式h2数据库
    @Autowired
    DataSource dataSource;
    
    @Autowired
    Securityhandler successHandler;
    
    @Autowired
    public void configure(AuthenticationManagerBuilder auth)
            throws Exception {
        auth.jdbcAuthentication()
            // 在h2数据库中查找登录信息
            .dataSource(dataSource)
            .usersByUsernameQuery("select email, password, 'true' as enabled from User where email = ?")        
            .authoritiesByUsernameQuery("select email, role " +
                            "from User " +
                            "where email =?");
        
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/*", "/h2-console/**").permitAll()
                .antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
                .antMatchers("/admin/**").hasRole("ADMIN")
                // formLogin 重定向到登录页面
                .and().formLogin()
                .successHandler(successHandler);
            
        
        // 为了与Spring安全CSRF保护一起使用,需要禁用csrf保护
        http.csrf().disable();
        http.headers().frameOptions().disable();

    }
    
    // 加密密码
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

通过commandlinerunner创建的Admin用户,因此在运行应用程序时会自动创建。注意末尾的admin角色。

@Override
public void run(String... args) throws Exception {
    // 在运行应用程序时创建新用户
    String password = securityConfig.passwordEncoder().encode("github");
    User user = new User("Billy", "billy", password, password, "sof@gmail.com", "ADMIN");
    userRep.save(user);
    System.out.println("已保存用户:" + user);
}

实体类:

@Entity
@ValidPassword
public class User {
    @Pattern(regexp="[a-zA-Z]+", message = "只输入字母!")
    private String firstName;
    @Pattern(regexp="[a-zA-Z]+", message = "只输入字母!")
    private String lastName;
    private String password;
    private String matchingPassword;
    private String passportNumber;
    private String address;
    private String phoneNumber;

    public String getEmail() {
        return email;
    }

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

    @ValidEmail
    private String email;

    // 标记为主键
    @Id
    // 将自动生成
    @GeneratedValue
    private long id;
    private String role;

    public User(String firstName, String lastName, String password, String passportNumber, String address,
            String phoneNumber, String email, String role) {
        super();
        this.firstName = firstName;
        this.lastName = lastName;
        this.password = password;
        this.passportNumber = passportNumber;
        this.address = address;
        this.phoneNumber = phoneNumber;
        this.email = email;
        this.role = role;
    }

    @Override
    public String toString() {
        return "User [firstName=" + firstName + ", lastName=" + lastName + ", password=" + password
                + ", matchingPassword=" + matchingPassword + ", passportNumber=" + passportNumber + ", address="
                + address + ", phoneNumber=" + phoneNumber + ", email=" + email + ", id=" + id + ", role=" + role + "]";
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }

    public String getPassword() {
        return password;
    }

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

    public String getMatchingPassword() {
        return matchingPassword;
    }

    public void setMatchingPassword(String matchingPassword) {
        this.matchingPassword = matchingPassword;
    }

    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 getPassportNumber() {
        return passportNumber;
    }

    public void setPassportNumber(String passportNumber) {
        this.passportNumber = passportNumber;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

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

    public User() {

    }

    public User(String firstName, String lastName, String password, String matchingPassword, String email,
            String role) {
        super();
        this.firstName = firstName;
        this.lastName = lastName;
        this.matchingPassword = matchingPassword;
        this.password = password;
        this.email = email;
        this.role = role;
    }

    public long getId() {
        return id;
    }
}

希望这对你有帮助!

英文:

I've a set rules where it dictates which roles have access to which url. However, I'm getting 403 at urls where the role should have access to. Please refer below for the code and problem

Log

> org.springframework.security.access.AccessDeniedException: Access is
> denied at
> org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84)
> ~[spring-security-core-5.3.3.RELEASE.jar:5.3.3.RELEASE] at
> org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233)
> ~[spring-security-core-5.3.3.RELEASE.jar:5.3.3.RELEASE] at
> org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:123)
> ~[spring-security-web-5.3.3.RELEASE.jar:5.3.3.RELEASE]

Spring security configuration. Notice admin/** allows admin usage. I've logged in with admin, going to admin/welcome and it gives me 403.

  @Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
// To access the h2 embedded database
@Autowired
DataSource dataSource;
@Autowired
Securityhandler successHandler;
@Autowired
public void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.jdbcAuthentication()
// To find logins in the h2 database
.dataSource(dataSource)
.usersByUsernameQuery("select email, password, 'true' as enabled from User where email = ?")		
.authoritiesByUsernameQuery("select email, role " +
"from User " +
"where email =?");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/*", "/h2-console/**").permitAll()
.antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.antMatchers("/admin/**").hasRole("ADMIN")
// formLogin redirect to login page
.and().formLogin()
.successHandler(successHandler);
// In order to work with spring security csrf protection needs to be disabled
http.csrf().disable();
http.headers().frameOptions().disable();
}
// To encrypt password
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}

Admin user created with commandlinerunner so it is automatically created upon running the app. Notice the admin role at the end

@Override
public void run(String... args) throws Exception {
// Creates new user upon running the app
String password = securityConfig.passwordEncoder().encode("github");
User user = new User("Billy", "billy", password, password, "sof@gmail.com", "ADMIN");
userRep.save(user);
System.out.println("Saved user:" + user);
}	

Entity class

@Entity
@ValidPassword
public class User {
@Pattern(regexp="[a-zA-Z]+", message = "Enter letters only!")
private String firstName;
@Pattern(regexp="[a-zA-Z]+", message = "Enter letters only!")
private String lastName;
private String password;
private String matchingPassword;
private String passportNumber;
private String address;
private String phoneNumber;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@ValidEmail
private String email;
// Mark as primary key
@Id
// Will be auto generated
@GeneratedValue
private long id;
private String role;
public User(String firstName, String lastName, String password, String passportNumber, String address,
String phoneNumber, String email, String role) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.password = password;
this.passportNumber = passportNumber;
this.address = address;
this.phoneNumber = phoneNumber;
this.email = email;
this.role = role;
}
@Override
public String toString() {
return "User [firstName=" + firstName + ", lastName=" + lastName + ", password=" + password
+ ", matchingPassword=" + matchingPassword + ", passportNumber=" + passportNumber + ", address="
+ address + ", phoneNumber=" + phoneNumber + ", email=" + email + ", id=" + id + ", role=" + role + "]";
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getMatchingPassword() {
return matchingPassword;
}
public void setMatchingPassword(String matchingPassword) {
this.matchingPassword = matchingPassword;
}
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 getPassportNumber() {
return passportNumber;
}
public void setPassportNumber(String passportNumber) {
this.passportNumber = passportNumber;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public void setId(long id) {
this.id = id;
}
public User() {
}
public User(String firstName, String lastName, String password, String matchingPassword, String email,
String role) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.matchingPassword = matchingPassword;
this.password = password;
this.email = email;
this.role = role;
}
public long getId() {
return id;
}

答案1

得分: 1

使用hasAuthority/hasAnyAuthority而不是hasRole/hasAnyRole,或者在创建用户时添加前缀ROLE_,正如@matejko219在他的评论中所写。

英文:

Use hasAuthority/hasAnyAuthority instead of hasRole/hasAnyRole or add the prefix ROLE_ when you create the user as @matejko219 wrote in his comment.

huangapple
  • 本文由 发表于 2020年8月6日 20:04:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/63283215.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定