@Roles在Spring启动时与configureGlobalSecurity jdbcAuthentication结合使用

时间:2017-11-14 03:21:05

标签: java spring spring-boot jdbc spring-security

使用@RolesAllowed时,

jdbcAuthentication()似乎不起作用,但如果我使用inMemoryAuthentication()则效果正常。如果我删除jdbcAuthentication(),则@RolesAllowed可以正常工作。

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
        auth.
            jdbcAuthentication()
            .usersByUsernameQuery("select u.email, u.password, u.enabled from bagtag.user u where email=?")
            .authoritiesByUsernameQuery("select u.email, r.name from bagtag.user u join bagtag.role r on (r.id = u.role_id) where u.email=?")
            .dataSource(dataSource)
            .passwordEncoder(bCryptPasswordEncoder);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable().authorizeRequests().antMatchers("/api/**").fullyAuthenticated().and().httpBasic()
                .realmName(REALM).authenticationEntryPoint(getBasicAuthEntryPoint()).and().sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    }
}

以下RequestMapping@RolesAllowed有效,但如果我删除@RolesAllowed则有效。我收到以下错误。

{
    "timestamp": 1510628906600,
    "status": 403,
    "error": "Forbidden",
    "exception": "org.springframework.security.access.AccessDeniedException",
    "message": "Access is denied",
    "path": "/api/user/admin"
} 

@RestController
@RequestMapping(value = "/api/user", produces = MediaType.APPLICATION_JSON_VALUE)
public class UserController {

    @Autowired
    UserService us;

    @RolesAllowed(Role.SUPERADMIN)
    @RequestMapping(value = "/admin", method = RequestMethod.POST)
    public ResponseEntity<User> createAdmin(@RequestBody UserWrapper uw) {
       return new ResponseEntity<User>(uw.getUser(), HttpStatus.OK);
    }
}

我尝试过检查经过身份验证的用户 System.out.println(SecurityContextHolder.getContext().getAuthentication().getPrincipal());

返回

org.springframework.security.core.userdetails.User@ca3b1db5: Username: test@test.dk; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: SUPERADMIN

我试图删除@RolesAllowed并替换了以下行 http.csrf().disable().authorizeRequests().antMatchers("/api/**").fullyAuthenticated().and().httpBasic()

http.csrf().disable().authorizeRequests().antMatchers("/api/**").hasAnyRole(String.format("%s,%s,%s", Role.SUPERADMIN, Role.ADMIN, Role.STAFF)).and().httpBasic()

这给了我http status 403

{
    "timestamp": 1510629419006,
    "status": 403,
    "error": "Forbidden",
    "message": "Access is denied",
    "path": "/api/user/admin"
}

这是我数据库中的两个表。用户只能拥有一个角色。

CREATE TABLE `role` (
   `role_id` int(11) NOT NULL AUTO_INCREMENT,
   `role` varchar(255) DEFAULT NULL,
   `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
   `updated` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
   PRIMARY KEY (`role_id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8

CREATE TABLE `user` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `email` varchar(255) NOT NULL,
   `password` varchar(255) NOT NULL,
   `first_name` varchar(255) NOT NULL,
   `last_name` varchar(255) DEFAULT NULL,
   `role_id` int(11) NOT NULL,
   `enabled` bit(1) NOT NULL DEFAULT b'0',
   `last_login` timestamp NULL DEFAULT NULL,
   `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
   `updated` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
   PRIMARY KEY (`id`),
   UNIQUE KEY `email_UNIQUE` (`email`),
 ) ENGINE=InnoDB AUTO_INCREMENT=44 DEFAULT CHARSET=utf8

1 个答案:

答案 0 :(得分:0)

所以我找到了问题的解决方案,我必须将.rolePrefix("ROLE_");添加到我的configureGlobalSecurity方法中。

我不确定为什么这是解决方案。根据文档,AuthenticationManagerBuilder的默认角色前缀为空String。所以我最好的猜测是Spring默认角色前缀是“ROLE _”。

如果有人知道这种疯狂背后的真实解释,请发表评论或回答。我会非常感谢!

编辑: @RolesAllowed默认前缀为ROLE_,这就是为什么你必须为spring security添加ROLE_前缀!

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
     public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
         auth.
            jdbcAuthentication()
            .usersByUsernameQuery(usersQuery)
            .authoritiesByUsernameQuery(rolesQuery)
            .dataSource(dataSource)
            .passwordEncoder(bCryptPasswordEncoder)
            //.rolePrefix fixed the problem
            .rolePrefix("ROLE_");           
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable().authorizeRequests().antMatchers("/api/**")
            .hasAnyRole(String.format("%s,%s,%s", Role.SUPERADMIN, Role.ADMIN, Role.STAFF)).and().httpBasic()
            .realmName(REALM).authenticationEntryPoint(getBasicAuthEntryPoint()).and().sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    }
}