使用Java配置在Spring Security为基于注解角色检查和基本的HTTP认证 [英] Using Java config with Spring Security for annotation-based role checks and Basic HTTP Auth

查看:2988
本文介绍了使用Java配置在Spring Security为基于注解角色检查和基本的HTTP认证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图完成的注释为基础的(使用 @ preAuthorize )权限在我的控制器之一检查。我使用Java的配置,并有一个 SecurityConfig 类扩展 WebSecurityConfigurerAdapter

我还使用基本HTTP认证才能到需要授权的方法。

但 - 问题是,我的不要希望 SecurityConfig 确定使用哪些方法需要身份验证的 antPattern ()或相似。这就是注解是!

如何配置我的 SecurityConfig 类,以便它正确地使用HTTP基本身份验证和配置的的AuthenticationManager 的方法与 @ preAuthorize ,并允许控制器的方法的的附加任何安全注解?

匿名访问

当我尝试这个(尝试#1):

  @Configuration
@EnableWebSecurity
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = TRUE)
公共类SecurityConfig扩展WebSecurityConfigurerAdapter {    @覆盖
    保护无效配置(HttpSecurity HTTP)抛出异常{
        。http.authorizeRequests()anyRequest()验证()和()httpBasic()。;
    }    @Autowired
    公共无效registerGlobal(AuthenticationManagerBuilder AUTH)抛出异常{
        。auth.inMemoryAuthentication()withUser(克雷格),密码(craigpass)的角色(用户)。;
    }
}

我的不受保护的方法失败:

全认证才能访问该资源

和我的保护(但正确-认证)测试失败,

错误:预期CSRF令牌没有找到。贵会话过期?

当我尝试这个(尝试#2):

  @Configuration
@EnableWebSecurity
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = TRUE)
公共类SecurityConfig扩展WebSecurityConfigurerAdapter {    @Autowired
    公共无效registerGlobal(AuthenticationManagerBuilder AUTH)抛出异常{
        。auth.inMemoryAuthentication()withUser(克雷格),密码(craigpass)的角色(用户)。;
    }
}

我的不受保护的方法失败了 302 状态code,并重定向到 /登录,和我的保护/验证方法失败:

错误:预期CSRF令牌没有找到。贵会话过期?

当我尝试这个(尝试3):

  @Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = TRUE)
公共类SecurityConfig扩展WebSecurityConfigurerAdapter {    @覆盖
    保护无效配置(HttpSecurity HTTP)抛出异常{
        http.csrf()禁用()authorizeRequests()anyRequest()验证()和()httpBasic()。。。。;
    }    @Autowired
    公共无效registerGlobal(AuthenticationManagerBuilder AUTH)抛出异常{
        。auth.inMemoryAuthentication()withUser(克雷格),密码(craigpass)的角色(用户)。;
    }
}

我的认证方法正常工作。 (宇豪!)但是,我的未受保护的方法失败, 401 ,因为我的 HttpSecurity 似乎已被配置为的只有的允许访问,如果你验证 - 无论控制器方法与 @ preAuthorize 注释

当我尝试这种(企图#4):

  @Configuration
@EnableWebSecurity
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = TRUE)
公共类SecurityConfig扩展WebSecurityConfigurerAdapter {    @覆盖
    保护无效配置(HttpSecurity HTTP)抛出异常{
        http.csrf()禁用()authorizeRequests()anyRequest()permitAll()。。
    }    @Autowired
    公共无效registerGlobal(AuthenticationManagerBuilder AUTH)抛出异常{
        。auth.inMemoryAuthentication()withUser(克雷格),密码(craigpass)的角色(用户)。;
    }
}

我的不受保护的方法正常工作(允许访问),但我的身份验证方法(他们是否有适当的HTTP认证与否)失败,状态code 403

错误:拒绝访问

我的认证测试方法失败与 403 使用 MockMvc 并在发送要求使用头文件:

{内容类型= [应用程序/ JSON],接受= [应用程序/ JSON],授权= [基本Y3JhaWc6Y3JhaWdwYXNz]}

这点我必须去codeD和验证,以及一个网址 / API /项目与方法 POST ,应针对相应的方法:

  @RequestMapping(值=/ API /项,方法= {} RequestMethod.POST)
@ preAuthorize(hasRole('ROLE_USER'))
公共无效postNewItem(HttpServletRequest的请求,HttpServletResponse的响应){
    ...
}


解决方案

我已经做过类似,唯一的区别是,我有一些非常定制的认证方法的东西。如果你想的唯一事情是检查用户角色,你应该使用 @Secured 而不是 @ preAuthorize 在你的控制器方法,例如

  @Secured({ROLE_SOMEROLE})
公共无效DoSomething的(...){
}

当角色在的AuthenticationProvider 设置为 SimpleGrantedAuthority UsernamePasswordAut​​henticationToken <列表/ code>。
下面是配置类:

  @Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(securedEnabled =真)
公共类SecurityConfig扩展WebSecurityConfigurerAdapter {@Autowired
私人的AuthenticationProvider authProvider;@Autowired
私人的AuthenticationEntryPoint的AuthenticationEntryPoint;@Autowired
公共无效configureGlobal(AuthenticationManagerBuilder AUTH)
        抛出异常{
    auth.authenticationProvider(authProvider);
}@覆盖
保护无效配置(HttpSecurity HTTP)抛出异常{
    //有一些其他的呼吁CORS Ajax请求。
    http.authorizeRequests()
            .antMatchers(/注销)
            .permitAll()
            .anyRequest()
            .authenticated()
            。和()
            .httpBasic()
            .authenticationEntryPoint(的AuthenticationEntryPoint)
            .csrf()
            .disable();
}}

如果你的方法被注解为 @Secured ,而当前用户没有指定的角色,客户端将收到一个 403 响应否则请求经过。如果您尝试运行单元测试,您可以使用 @profile('测试')您豆类和使用的AuthenticationProvider 硬codeD数据。在这里,对这种类型的方法后:
https://spring.io/blog/ 2011/02/14 /春天-3-1-M1-引入瞩目/

I'm trying to accomplish annotation-based (using @PreAuthorize) permission checking on one of my controllers. I'm using Java config, and have a SecurityConfig class extending WebSecurityConfigurerAdapter.

I'm also using Basic HTTP Authentication to get to the methods that require authorization.

But - the problem is, I don't want the SecurityConfig determining which methods require authentication using an antPattern() or similar. That's what the annotations are for!

How can I configure my SecurityConfig class so that it properly uses HTTP Basic authentication and the configured AuthenticationManager for methods with @PreAuthorize, and allows anonymous access to controller methods that do not have any security annotations attached?

When I try this (Attempt #1):

@Configuration
@EnableWebSecurity
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
    }

    @Autowired
    public void registerGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("craig").password("craigpass").roles("USER");
    }
}

My unprotected methods fail with:

Full authentication is required to access this resource

And my protected (but properly-authenticating) tests fail with:

Error: Expected CSRF token not found. Has your session expired?

When I try this (Attempt #2):

@Configuration
@EnableWebSecurity
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void registerGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("craig").password("craigpass").roles("USER");
    }
}

My unprotected methods fail with a 302 status code, and redirect to /login, and my protected/authenticating methods fail with:

Error: Expected CSRF token not found. Has your session expired?

When I try this (Attempt #3):

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests().anyRequest().authenticated().and().httpBasic();
    }

    @Autowired
    public void registerGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("craig").password("craigpass").roles("USER");
    }
}

My authenticating method works properly. (Woo hoo!) But, my unprotected method fails with 401 because my HttpSecurity has seemingly been configured to only allow access if you're authenticated - regardless of whether the controller method is annotated with @PreAuthorize.

When I try this (Attempt #4):

@Configuration
@EnableWebSecurity
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests().anyRequest().permitAll();
    }

    @Autowired
    public void registerGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("craig").password("craigpass").roles("USER");
    }
}

My unprotected methods work properly (allow access), but my authenticating methods (whether they have the proper HTTP auth or not) fail with status code 403:

Error: Access Denied

My authenticating test method that fails with 403 uses MockMvc and sends in a request using headers:

{Content-Type=[application/json], Accept=[application/json], Authorization=[Basic Y3JhaWc6Y3JhaWdwYXNz]}

Which I have decoded and verified, and a URL /api/item with method POST, which should target the corresponding method:

@RequestMapping(value = "/api/item", method = { RequestMethod.POST })
@PreAuthorize("hasRole('ROLE_USER')")
public void postNewItem(HttpServletRequest request, HttpServletResponse response) {
    ...
}

解决方案

I've done something similar the only difference is that i had some very customized authentication method. If the only thing you want is to check for user role you should use @Secured instead of @PreAuthorize on your controller methods e.g.

@Secured({"ROLE_SOMEROLE"})
public void doSomething(...) {
}

Where the role is set in AuthenticationProvider as a list of SimpleGrantedAuthority with UsernamePasswordAuthenticationToken. Here is the configuration class:

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(securedEnabled=true)
public class SecurityConfig  extends WebSecurityConfigurerAdapter {

@Autowired
private AuthenticationProvider authProvider;

@Autowired
private AuthenticationEntryPoint authenticationEntryPoint;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
        throws Exception {
    auth.authenticationProvider(authProvider);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    // Had some other calls for CORS ajax requests.
    http.authorizeRequests()
            .antMatchers("/logout")
            .permitAll()
            .anyRequest()
            .authenticated()
            .and()
            .httpBasic()
            .authenticationEntryPoint(authenticationEntryPoint)
            .csrf()
            .disable();
}

}

If your methods are annotated with @Secured and the current user does not have specified role the client will receive a 403 response else the request goes through. If you are trying to run unit testing you can use @Profile('test') on your beans and use AuthenticationProvider with hard coded data. Here a post on this type of approach: https://spring.io/blog/2011/02/14/spring-3-1-m1-introducing-profile/

这篇关于使用Java配置在Spring Security为基于注解角色检查和基本的HTTP认证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆