403禁止访问 – Spring安全

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

403 forbidden - Spring Security

问题

我正在尝试使用Spring Security来保护我的网站,但我一直收到403 Forbidden错误。我已经在网上看过许多帖子,但没有一个适用于我的情况。

我正在使用Springboot构建后端REST API,并使用Postman进行测试。

我已经禁用了 http.csrf().disable(); 但仍然出现403错误

我可以访问所有用户都有权限的部分,它也能识别出我输入的错误凭据,但当我尝试访问只有具有ADMINUSER角色的用户才能访问的部分时,立即出现以下错误。

{
    "timestamp": "2020-08-30T02:08:36.033+00:00",
    "status": 403,
    "error": "Forbidden",
    "message": "",
    "path": "/secure/auth/addUser"
}

SecurityConfiguration.java

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

   @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .userDetailsService(userDetailsService)
                .passwordEncoder(encodePWD());
    }

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

        http.csrf().disable();
        http
                .httpBasic()
                .and()
                .authorizeRequests()
                .antMatchers("/rest/**").permitAll()
                .and()
                .authorizeRequests()
                .antMatchers("/secure/**").hasAnyRole("ADMIN")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .permitAll();
    }

    @Bean
    public BCryptPasswordEncoder encodePWD() {
        return new BCryptPasswordEncoder();
    }
}

CustomUserDetailsService.java

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        CustomUserDetails userDetails = null;

        if(user != null){
            userDetails = new CustomUserDetails();
            userDetails.setUser(user);
        }else{
            throw new UserNotFoundException("User doesn't exist with this username: " + username);
        }
        return userDetails;
    }
}

CustomUserDetails.java

@Getter
@Setter
public class CustomUserDetails implements UserDetails {

    private User user;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return user.getRoles().stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role)).collect(Collectors.toSet());
    }
    
    @Override
    public String getPassword() {
        return user.getPassword();
    }

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

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

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

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

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

UserController.java

@RequestMapping("/secure/auth/")
public class UserController {

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @PreAuthorize("hasAnyRole('ADMIN')")
    // POST method for adding one user
    @PostMapping("/addUser")
    public User addUser(@RequestBody User user){
        String pwd = user.getPassword();
        String encriptPwd = passwordEncoder.encode(pwd);
        user.setPassword(encriptPwd);
        return service.saveUser(user);
    }
    //other code needed
}

BookContoller.java

@RestController
@RequestMapping("/rest/auth")
public class BookContoller {

    @Autowired
    private BookService service;

    // GET method display all books
    @GetMapping("/books")
    public List<Book> findAllBooks(){
        return service.getAllBooks();
    }
}

更新

当我调试以下代码部分时:

return user.getRoles().stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role)).collect(Collectors.toSet());

我得到了我用来登录的用户:

User(id=1, name=chad, surname=huskins, username=chad, email=chad.huskins@gmail.com, password=$2a$10$SMH1T6fQ4HqzTAop.XOR/eDlfKzyjSkGGsT/qDCy1JYnncpdkqv32, roles=[Role(id=1, role=ADMIN)])

User.java

public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String name;
    private String surname;
    private String username;
    private String email;
    private String password;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
    private Set<Role> roles;

    public Set<Role> getRoles() {
        return roles;
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }
}

Role.java

@Table(name = "Roles")
public class Role {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String role;
}
英文:

I'm trying to secure my website using Spring security but I am keep getting 403 Forbidden error. I have seen many posts online but none was applying for my situation.

I am building a backend RESTapi using Springboot and I am testing it with Postman.

I have disabled http.csrf().disable(); but still 403 error is there.

I can access part where all users have permition It also recognizes if I put bad credentials but when I try to access part where only user with role ADMIN or USER have access I immediately have following error.

{
    &quot;timestamp&quot;: &quot;2020-08-30T02:08:36.033+00:00&quot;,
    &quot;status&quot;: 403,
    &quot;error&quot;: &quot;Forbidden&quot;,
    &quot;message&quot;: &quot;&quot;,
    &quot;path&quot;: &quot;/secure/auth/addUser&quot;
 }

SecurityConfiguration.java

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

   @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .userDetailsService(userDetailsService)
                .passwordEncoder(encodePWD());
    }

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

        http.csrf().disable();
        http
                .httpBasic()
                .and()
                .authorizeRequests()
                .antMatchers(&quot;/rest/**&quot;).permitAll()
                .and()
                .authorizeRequests()
                .antMatchers(&quot;/secure/**&quot;).hasAnyRole(&quot;ADMIN&quot;)
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .permitAll();


    }

    @Bean
    public BCryptPasswordEncoder encodePWD() {
        return new BCryptPasswordEncoder();
    }


}

CustomUserDetailsService.java

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        CustomUserDetails userDetails = null;

        if(user != null){
            userDetails = new CustomUserDetails();
            userDetails.setUser(user);
        }else{
            throw new UserNotFoundException(&quot;User doesn&#39;t exist with this username: &quot; + username);
        }
        return userDetails;

    }

}

CustomUserDetails.java

@Getter
@Setter
public class CustomUserDetails implements UserDetails {

    private User user;

    @Override
    public Collection&lt;? extends GrantedAuthority&gt; getAuthorities() {
        return user.getRoles().stream().map(role -&gt; new SimpleGrantedAuthority(&quot;ROLE_&quot; + role)).collect(Collectors.toSet());

    }
    
    @Override
    public String getPassword() {
        return user.getPassword();
    }

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

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

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

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

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

}

UserController. java

@RequestMapping(&quot;/secure/auth/&quot;)
public class UserController {

 @Autowired
    private BCryptPasswordEncoder passwordEncoder;

 @PreAuthorize(&quot;hasAnyRole(&#39;ADMIN&#39;)&quot;)
    //POST method for adding one user
    @PostMapping(&quot;/addUser&quot;)
    public User addUser(@RequestBody User user){
        String pwd = user.getPassword();
        String encriptPwd = passwordEncoder.encode(pwd);
        user.setPassword(encriptPwd);
        return service.saveUser(user);
    }

//other code needed
}

BookContoller.java

@RestController
@RequestMapping(&quot;/rest/auth&quot;)
public class BookContoller {

    @Autowired
    private BookService service;

    //GET method display all books
    @GetMapping(&quot;/books&quot;)
    public List&lt;Book&gt; findAllBooks(){
        return service.getAllBooks();
    }

UPDATE

When I debug part of code with

return user.getRoles().stream().map(role -&gt; new SimpleGrantedAuthority(&quot;ROLE_&quot; + role)).collect(Collectors.toSet());

I get back User that I am using to log in...

User(id=1, name=chad, surname=huskins, username=chad, email=chad.huskins@gmail.com, password=$2a$10$SMH1T6fQ4HqzTAop.XOR/eDlfKzyjSkGGsT/qDCy1JYnncpdkqv32, roles=[Role(id=1, role=ADMIN)])

User.java

public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String name;
    private String surname;
    private String username;
    private String email;
    private String password;

    //@OneToMany(mappedBy = &quot;user&quot;, cascade = CascadeType.ALL)
    //private List&lt;Rent&gt; rent = new ArrayList&lt;&gt;();

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(name = &quot;user_role&quot;, joinColumns = @JoinColumn(name = &quot;user_id&quot;), inverseJoinColumns = @JoinColumn(name = &quot;role_id&quot;))
    private Set&lt;Role&gt; roles;
    
    public Set&lt;Role&gt; getRoles() {
        return roles;
    }

    public void setRoles(Set&lt;Role&gt; roles) {
        this.roles = roles;
    }
}

Role.java

@Table(name = &quot;Roles&quot;)
public class Role {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String role;
}

答案1

得分: 1

使用new SimpleGrantedAuthority("ROLE_" + role.getRole()))替代new SimpleGrantedAuthority("ROLE_" + role))

英文:

Use new SimpleGrantedAuthority(&quot;ROLE_&quot; + role.getRole())) instead of new SimpleGrantedAuthority(&quot;ROLE_&quot; + role))

huangapple
  • 本文由 发表于 2020年8月30日 17:32:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/63656011.html
匿名

发表评论

匿名网友

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

确定