【问题标题】:Spring Security: issues 403 after authorization with single grantedSpring Security:授权单授权后发出 403
【发布时间】:2020-03-20 05:52:14
【问题描述】:

使用 Spring Boot 2 + Spring Security Starter。

授权用户,但由于某种原因给出错误403。

我尝试用不同的方式进行配置,但它不起作用。

授权成功后(loadUserByUsername 方法工作正常)它在所有带有 /admin 前缀的页面上显示 403,在授权之前,切换到带有此前缀的任何页面都会导致重定向到 /login

@Controller
public class AdminController {
    @RequestMapping(value = "/admin", method = {GET, POST})
    public String adminMainPage() {
        return "redirect:/admin/article";
    }
}

@Controller
@RequestMapping("/admin/article")
public class ArticleController {
  @RequestMapping(value = "", method = {GET, POST})
  public ModelAndView indexAdminPage(...){
  ...
  }
}

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements UserDetailsService {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .userDetailsService(this)
                .authorizeRequests()
                .antMatchers("/", "/login",
                        "/login*", "/assets/**", "/lib/**", "/page.scripts/*").permitAll()
                .antMatchers("/admin/**").hasAnyRole("ADMIN")
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .usernameParameter("login")
                .passwordParameter("password")
                .successForwardUrl("/admin")
                .permitAll()
                .and()
                .logout()
                .deleteCookies("JSESSIONID")
                .permitAll();
    }

    private Collection<? extends GrantedAuthority> adminGrantedAuthoritySet = new HashSet<>() {{
        add(new SimpleGrantedAuthority("ADMIN"));
    }};

    private final UserRepository userRepository;

    public WebSecurityConfig(UserRepository userRepository ) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException {
        Optional<UserEntity> optionalUser = userRepository.findByLogin(login);
        if (optionalUser.isEmpty()) {
            throw new UsernameNotFoundException("User by login '" + login + "' not found");
        } else {
            UserEntity userEntity = optionalUser.get();
            return new User(login, userEntity.getPassword(), adminGrantedAuthoritySet);
        }
    }
}

【问题讨论】:

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


    【解决方案1】:

    在 Spring Security 中,roleauthority 之间存在区别。
    role 是一个以 "ROLE_" 为前缀的 authority。在此示例中,权限"ROLE_ADMIN" 与角色"ADMIN" 相同。

    您将您的管理员authorities 设置为new SimpleGrantedAuthority("ADMIN") 的列表,但您限制了对.hasAnyRole("ADMIN") 的访问。

    您需要更改其中一项配置。
    如果您使用.hasAnyRole("ADMIN"),则应将管理员authorities 列表更改为使用new SimpleGrantedAuthority("ROLE_ADMIN")
    否则,如果您希望您的列表为new SimpleGrantedAuthority("ADMIN"),那么您应该使用.hasAnyAuthority("ADMIN")

    【讨论】:

      【解决方案2】:

      首先,我建议您将 UserDetailsS​​ervice 与 WebSecurityConfig 分开。

      为 UserDetailsS​​ervice 提供一个单独的类,例如

      @Service("customCustomerDetailsService")
      public class CustomCustomerDetailsService implements UserDetailsService  {
      
          @Autowired
          private CustomerRepository customers;    
      
      
      
      
          @Override
          public UserDetails loadUserByUsername(String email)  {
      
            return this.customers.findByEmail(email)
                  .orElseThrow(() -> new UsernameNotFoundException("Username: " + email + " not found"));
      
      
      
          }
      
      }
      

      那么你的 UserEntity 应该在你设置权限的地方实现 UserDetails 类。查看答案 //userdetails

      @Override
          public Collection<? extends GrantedAuthority> getAuthorities() {
              return this.roles.stream().map(SimpleGrantedAuthority::new).collect(toList());
          }
      
      
          @Override
          public String getUsername() {
      
              return this.getEmail();
          }
      
      
          @Override
          public boolean isAccountNonExpired() {
      
              return true;
          }
      
      
          @Override
          public boolean isAccountNonLocked() {
              return true;
          }
      
      
          @Override
          public boolean isCredentialsNonExpired() {
              return true;
          }
      
      
          @Override
          public boolean isEnabled() {
              return true;
          }
      
          @Transient
          private List<String> roles = Arrays.asList("ROLE_USER");
          public List<String> getRoles() {
              return roles;
          }
      

      然后你需要 DAOauthentication 管理器,它像这样使用 UserDetailsS​​ervice:

      @Bean
          public DaoAuthenticationProvider authenticationProvider() {
              DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
              authProvider.setUserDetailsService(userDetailsService());
              authProvider.setPasswordEncoder(encoder());
      
              return authProvider;
      
          }
      @Bean
          @Override
          public UserDetailsService userDetailsService() {
      
              return new CustomCustomerDetailsService();
      
          }
      

      我不知道将所有内容都放在 WebSecurityConfig 中是一种好习惯,它会很复杂并且容易出错!

      【讨论】:

        猜你喜欢
        • 2022-01-06
        • 2013-03-15
        • 2016-08-08
        • 2017-04-20
        • 2020-04-25
        • 2016-03-14
        • 1970-01-01
        • 2014-05-10
        • 2013-12-01
        相关资源
        最近更新 更多