Spring Security:授权后发出 403 单授权
Posted
技术标签:
【中文标题】Spring Security:授权后发出 403 单授权【英文标题】:Spring Security: issues 403 after authorization with single granted 【发布时间】:2022-01-06 20:24:56 【问题描述】:使用 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);
【问题讨论】:
【参考方案1】:在 Spring Security 中,role
和 authority
之间存在区别。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】:首先,我建议您将 UserDetailsService 与 WebSecurityConfig 分开。
为 UserDetailsService 提供一个单独的类,例如
@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 管理器,它像这样使用 UserDetailsService:
@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 中是一种好习惯,它会很复杂并且容易出错!
【讨论】:
以上是关于Spring Security:授权后发出 403 单授权的主要内容,如果未能解决你的问题,请参考以下文章
AJAX / Spring MVC - 没有 Spring Security 的 403 禁止错误
Spring security UsernamePasswordAuthenticationToken 始终返回 403:用户凭据已过期
登录后 Spring Security 总是返回 403 accessDeniedPage [重复]
Spring Security + Angular App REST Token Based Authentication = 403 Forbidden on POST
在 Grails 3 应用程序中使用 Spring Security Rest 对“refresh_token”请求的 403 响应