我做了很多研究,对我而言,一切看起来都很正确......但是我无法让它发挥作用!任何人都有任何想法?
无论我做什么,相关的映射仍然公开给任何人(匿名或登录,无论他们有什么角色)。
理想情况下,我希望所有请求都是公共的,除了那些由@Secured()注释的请求 - 显然只有具有特定角色的用户才能访问这些映射。
这可能吗?
作为一种变通方法,我目前建立了一种方法" hasRole(String role)"它检查登录用户的角色,如果方法返回false,则抛出NotAuthorizedException(自定义)。
的UserDetails
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> grantedAuthorities = null;
System.out.print("Account role... ");
System.out.println(account.getRole());
if (account.getRole().equals("USER")) {
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_USER");
grantedAuthorities = Arrays.asList(grantedAuthority);
}
if (account.getRole().equals("ADMIN")) {
GrantedAuthority grantedAuthorityUser = new SimpleGrantedAuthority("ROLE_USER");
GrantedAuthority grantedAuthorityAdmin = new SimpleGrantedAuthority("ROLE_ADMIN");
grantedAuthorities = Arrays.asList(grantedAuthorityUser, grantedAuthorityAdmin);
}
return grantedAuthorities;
}
SecurityConfig
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthFailure authFailure;
@Autowired
private AuthSuccess authSuccess;
@Autowired
private EntryPointUnauthorizedHandler unauthorizedHandler;
@Autowired
private UserDetailsServiceImpl userDetailsService;
/*@Autowired
public void configAuthBuilder(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(userDetailsService);
}*/
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Autowired
@Override
public void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(userDetailsService);
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().csrfTokenRepository(csrfTokenRepository())
.and().exceptionHandling().authenticationEntryPoint(unauthorizedHandler)
.and().formLogin().loginPage("/login").successHandler(authSuccess).failureHandler(authFailure)
//.and().authorizeRequests().antMatchers("/rest/**").authenticated()
//.and().authorizeRequests().antMatchers("/**").permitAll()
.and().addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);;
}
的AccountController
@Secured("ROLE_USER")
@RequestMapping(method = RequestMethod.GET)
public List<Account> getAllAccounts(@RequestParam(value = "mail", required = false) String mail) {
谢谢!
答案 0 :(得分:5)
您可以使用Spring HttpSecurity控制器作用域安全性。尝试将此添加到您的配置方法:
.antMatchers("rest/accounts*").hasRole("ADMIN")
如果您希望任何请求公开(真的吗?):
.anyRequest().permitAll()
当您从任何地方访问它时,您还可以在UserDetailsService中保护您的Methodinvocation for Example:
@Secured("ROLE_USER")
public getAllAccounts(...){...}
只有这样你才需要用以下方法注释你的SecurityConfig:
@EnableGlobalMethodSecurity(securedEnabled = true)
在实践中,我们建议您在服务中使用方法安全性 图层,用于控制对应用程序的访问,并且不完全依赖 关于在web应用程序中定义的安全性约束的使用 水平。网址发生变化,很难将其全部考虑在内 应用程序可能支持的可能URL以及请求的可能方式 被操纵。你应该试着限制自己使用一些 简单的蚂蚁路径,易于理解。总是尝试使用 一个&#34;拒绝按默认&#34;你有一个全能通配符的方法(/或 )最后定义并拒绝访问。在服务中定义的安全性 图层更加强大,更难以绕过,因此您应该始终如此 利用Spring Security的方法安全选项。
答案 1 :(得分:1)
在这里,我想根据sven.kwiotek的上述正确答案添加一些内容。如果在ROLE表中您仍要使用“ USER”,“ ADMIN” ...,该解决方案也很简单:
例如,从数据库中获取角色时,请不要忘记手动添加“ ROLE_”前缀,
List<GrantedAuthority> authorities = user.getRoles().stream().map(role ->
new SimpleGrantedAuthority("ROLE_" + role.getRole()))
.collect(Collectors.toList());
然后可以安全地在控制器方法中使用注释@Secured("ROLE_USER")
。
原因是在org.springframework.security.access.vote.RoleVoter
类中,所有角色都应以 ROLE _ 前缀开头。