且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Spring Boot集成Security使用数据库用户角色权限ROLE_问题

更新时间:2022-06-03 00:09:36

问题描述

日志打出来的ROLE是USER,代码里调用的是@PreAuthorize("hasRole('USER')"),为什么权限却是不对?

后台打印日志:

username is jack, USER
LoginFilter:{
"accountNonExpired":true,
"accountNonLocked":true,
"authorities":[{
"authority":"USER"
}],
"credentialsNonExpired":true,
"enabled":true,
"username":"jack"
}

调用代码:

@RestController
@RequestMapping(Array("/httpapi"))
class HttpApiController @Autowired()(
                                      val HttpSuiteDao: HttpSuiteDao,
                                      val HttpApiDao: HttpApiDao,
                                      val HttpReportDao: HttpReportDao) {

  @PreAuthorize("hasRole('USER')")
  @RequestMapping(value = {
    Array("", "/")
  }, method = Array(RequestMethod.GET))
  def list(model: Model) = {
    model.addAttribute("httpapis", HttpApiDao.findAll())
    new ModelAndView("/httpapi/list")
  }

....


}

数据库存的是USER:

package com.springboot.in.action.service

import javax.annotation.PostConstruct

import com.springboot.in.action.dao.{RoleDao, UserDao, UserRoleDao}
import com.springboot.in.action.entity.{Role, User, UserRole}
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service

/**
  * Created by jack on 2017/4/29.
  * 初始化测试数据
  */
//@Service // 需要初始化数据时,打开注释即可。
class DataInit @Autowired()(val userDao: UserDao,
                            val userRoleDao: UserRoleDao,
                            val roleDao: RoleDao) {

  @PostConstruct def dataInit(): Unit = {
    val admin = new User
    val jack = new User

    admin.username = "admin"
    admin.password = "admin"

    jack.username = "jack"
    jack.password = "123456"

    userDao.save(admin)
    userDao.save(jack)

    val adminRole = new Role
    val userRole = new Role

    adminRole.role = "ADMIN"
    userRole.role = "USER"

    roleDao.save(adminRole)
    roleDao.save(userRole)

    val userRoleAdminRecord1 = new UserRole
    userRoleAdminRecord1.userId = admin.id
    userRoleAdminRecord1.roleId = adminRole.id
    userRoleDao.save(userRoleAdminRecord1)

    val userRoleAdminRecord2 = new UserRole
    userRoleAdminRecord2.userId = admin.id
    userRoleAdminRecord2.roleId = userRole.id
    userRoleDao.save(userRoleAdminRecord2)

    val userRoleJackRecord = new UserRole
    userRoleJackRecord.userId = jack.id
    userRoleJackRecord.roleId = userRole.id
    userRoleDao.save(userRoleJackRecord)


  }

}


原因分析:

Spring Security默认前缀ROLE_问题。这个应该是框架的一个小缺陷。总感觉这样的一个潜规则在这里有点不大优雅。

解决方案

数据库里面存的role角色要加上默认前缀:ROLE_


    adminRole.role = "ROLE_ADMIN"
    userRole.role = "ROLE_USER"

这样改完之后,代码调用的地方保持不变,数据库里面角色必须统一有ROLE_前缀。而我们看到的后台打印的日志内容也是数据库的信息:

username is jack, ROLE_USER
LoginFilter:{
    "accountNonExpired":true,
    "accountNonLocked":true,
    "authorities":[{
        "authority":"ROLE_USER"
    }],
    "credentialsNonExpired":true,
    "enabled":true,
    "username":"jack"
}

这个小坑,估计很多初次学习使用Security框架的人都会踩到。所以,记个问题,以供参考。