【问题标题】:Spring security 403 error despite CSRF disabled [duplicate]尽管禁用了 CSRF,但 Spring 安全性 403 错误 [重复]
【发布时间】:2020-08-06 12:04:06
【问题描述】:

我有一套规则,它规定哪些角色可以访问哪个网址。但是,我在角色应该有权访问的 url 上得到 403。代码和问题请参考下面

日志

org.springframework.security.access.AccessDeniedException: 访问是 拒绝于 org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-5.3.3.RELEASE.jar:5.3.3.RELEASE] 在 org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-5.3.3.RELEASE.jar:5.3.3.RELEASE] 在 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 登录,进入 admin/welcome,它给了我 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();
        }
    }

使用 commandlinerunner 创建的管理员用户,因此它是在运行应用程序时自动创建的。注意最后的管理员角色

@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
@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;
    }

【问题讨论】:

  • SecurityContextHolder.getContext().getAuthentication().getAuthorities() 调试您的权限并检查角色名称是否不同(以ROLE_ 为前缀)?

标签: java spring spring-boot spring-mvc spring-security


【解决方案1】:

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

【讨论】:

猜你喜欢
  • 2018-01-14
  • 1970-01-01
  • 2020-01-17
  • 1970-01-01
  • 2021-06-21
  • 2016-05-06
  • 1970-01-01
  • 2015-04-12
  • 2015-08-18
相关资源
最近更新 更多