无法在Spring Security中获取@Secured Method Security注释

时间:2015-03-26 10:15:02

标签: java spring spring-security annotations

我做了很多研究,对我而言,一切看起来都很正确......但是我无法让它发挥作用!任何人都有任何想法?

无论我做什么,相关的映射仍然公开给任何人(匿名或登录,无论他们有什么角色)。

理想情况下,我希望所有请求都是公共的,除了那些由@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) {

谢谢!

2 个答案:

答案 0 :(得分:5)

您可以使用Spring HttpSecurity控制器作用域安全性。尝试将此添加到您的配置方法:

.antMatchers("rest/accounts*").hasRole("ADMIN")

如果您希望任何请求公开(真的吗?):

.anyRequest().permitAll()

当您从任何地方访问它时,您还可以在UserDetailsS​​ervice中保护您的Methodinvocation for Example:

@Secured("ROLE_USER")
public getAllAccounts(...){...}

只有这样你才需要用以下方法注释你的SecurityConfig:

@EnableGlobalMethodSecurity(securedEnabled = true)
  

在实践中,我们建议您在服务中使用方法安全性   图层,用于控制对应用程序的访问,并且不完全依赖   关于在web应用程序中定义的安全性约束的使用   水平。网址发生变化,很难将其全部考虑在内   应用程序可能支持的可能URL以及请求的可能方式   被操纵。你应该试着限制自己使用一些   简单的蚂蚁路径,易于理解。总是尝试使用   一个&#34;拒绝按默认&#34;你有一个全能通配符的方法(/或   )最后定义并拒绝访问。在服务中定义的安全性   图层更加强大,更难以绕过,因此您应该始终如此   利用Spring Security的方法安全选项。

请参阅:http://docs.spring.io/autorepo/docs/spring-security/4.0.0.CI-SNAPSHOT/reference/htmlsingle/#request-matching

答案 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 _ 前缀开头。