简体   繁体   English

无法在Spring Security中使用@Secured Method Security批注

[英]Can not get the @Secured Method Security annotations working in Spring Security

I have done a lot of Research and to me everything looks right... but I cannot get this to work! 我做了很多研究,对我来说一切看起来都不错……但是我无法使它正常工作! Anyone has any idea? 有人知道吗?

No matter what I do, the relevant mapping remains public to anyone (anonymous or logged in, no matter what Role they have). 不管我做什么,相关的映射对任何人都保持公开(匿名或登录,无论他们具有什么角色)。

Ideally I would like to have ALL requests to be Public, except those which are annotated by @Secured() - obviously only the users with the specific roles would be allowed access to these mappings. 理想情况下,我希望所有请求都公开,但@Secured()注释的请求除外-显然,只有具有特定角色的用户才能访问这些映射。

Is that possible? 那可能吗?

FYI as a workaround I currently built a method "hasRole(String role)" which checks the role of the logged-in user, and throws a NotAuthorizedException (custom made) if the method returns false. 仅供参考,我目前构建了一种方法“ hasRole(String role)”,该方法检查登录用户的角色,如果该方法返回false,则抛出NotAuthorizedException(定制)。

UserDetails 的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 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 的AccountController

  @Secured("ROLE_USER")
  @RequestMapping(method = RequestMethod.GET)
  public List<Account> getAllAccounts(@RequestParam(value = "mail", required = false) String mail) {

Thanks! 谢谢!

You can make use of Controller scoped Security with Spring HttpSecurity. 您可以使用带有Spring HttpSecurity的Controller范围安全性。 Try add this to your configure Method: 尝试将其添加到您的configure方法中:

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

And if you wish ANY Request to be public (really?): 如果您希望任何要求公开(真的吗?):

.anyRequest().permitAll()

You can additionally secure your Methodinvocation for Example in your UserDetailsService when you access it from anywhere: 当您从任何地方访问它时,还可以在UserDetailsS​​ervice中保护示例的Methodinvocation:

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

Only then you have to annotate your SecurityConfig with: 只有这样,您才需要使用以下方法注释SecurityConfig:

@EnableGlobalMethodSecurity(securedEnabled = true)

In practice we recommend that you use method security at your service layer, to control access to your application, and do not rely entirely on the use of security constraints defined at the web-application level. 在实践中,我们建议您在服务层使用方法安全性来控制对应用程序的访问,并且不要完全依赖于在Web应用程序级别定义的安全性约束的使用。 URLs change and it is difficult to take account of all the possible URLs that an application might support and how requests might be manipulated. URL会发生变化,很难考虑应用程序可能支持的所有可能的URL以及如何处理请求。 You should try and restrict yourself to using a few simple ant paths which are simple to understand. 您应该尝试限制自己使用一些简单易懂的简单蚂蚁路径。 Always try to use a"deny-by-default" approach where you have a catch-all wildcard ( / or ) defined last and denying access. 始终尝试使用“默认拒绝”方法,在此方法中,您最后定义了一个全包通配符(/或),并拒绝访问。 Security defined at the service layer is much more robust and harder to bypass, so you should always take advantage of Spring Security's method security options. 在服务层定义的安全性更健壮,更难绕开,因此您应该始终利用Spring Security的方法安全性选项。

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

Here, I would like to add something based on the above right answer from sven.kwiotek. 在这里,我想根据sven.kwiotek的上述正确答案添加一些内容。 If in the ROLE table you still want to use "USER", "ADMIN"... the solution is also easy: 如果在ROLE表中仍要使用“ USER”,“ ADMIN” ...,该解决方案也很简单:

When fetch the role from database, do not forget to add "ROLE_" prefix manully, for example, 从数据库获取角色时,请不要忘记手动添加“ ROLE_”前缀,例如,

List<GrantedAuthority> authorities = user.getRoles().stream().map(role -> 
    new SimpleGrantedAuthority("ROLE_" + role.getRole()))
    .collect(Collectors.toList());

and then you could use annotation @Secured("ROLE_USER") in the controller method with safety. 然后可以安全地在控制器方法中使用注释@Secured("ROLE_USER")

The reason is that in the org.springframework.security.access.vote.RoleVoter class all roles should start with ROLE_ prefix. 原因是在org.springframework.security.access.vote.RoleVoter类中,所有角色都应以ROLE_前缀开头。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM