SpringBoot2.X Security JWT 登錄授權認證
目前在java后端的開發(fā)項目中,授權認證這個功能基本是必備的,這里只講常用的登錄授權認證,Spring Security + JWT(java web token)。
Spring Security 官網(wǎng)介紹
https://spring.io/projects/spring-security

官網(wǎng)文檔說明:
https://docs.spring.io/spring-security/site/docs/5.4.1/reference/html5/

SpringSecurity是一個強大的可高度定制的認證和授權框架,
對于Spring應用來說它是一套Web安全標準。SpringSecurity注重于為Java應用提供認證和授權功能,
像所有的Spring項目一樣,它對自定義需求具有強大的擴展性。
JWT是JSON WEB TOKEN的縮寫,它是基于 RFC 7519 標準定義的一種可以安全傳輸?shù)牡腏SON對象,
由于使用了數(shù)字簽名,所以是可信任和安全的。
JWT的組成
JWT token的格式:header.payload.signature
1.header中用于存放簽名的生成算法 {"alg": "HS512"}
2.payload中用于存放用戶名、token的生成時間和過期時間
{"sub":"admin","created":1489079981393,"exp":1489684781}
3.signature為以header和payload生成的簽名,一旦header和payload被篡改,驗證將失敗
//secret為加密算法的密鑰
String signature = HMACSHA512(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)
直接上案例:
gihub 代碼地址:https://github.com/LaiHouWen/SpringSecurityJwt
項目借鑒 開源項目 mall商城,http://www.macrozheng.com/#/architect/mall_arch_04,剝離出來的。
先準備一張用戶表admin,角色表role,用戶權限表permission,用戶和角色關系表,用戶與角色是多對多關系admin_role_relation,用戶角色和權限關系表,角色與權限是多對多關系role_permission_relation,用戶和權限關系表admin_permission_relation。
admin表sql
DROP TABLE IF EXISTS `admin`;
CREATE TABLE `admin` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`password` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`email` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '郵箱',
`nick_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '昵稱',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '創(chuàng)建時間',
`login_time` datetime(0) NULL DEFAULT NULL COMMENT '最后登錄時間',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用戶表' ROW_FORMAT = Dynamic;
role表SQL
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '名稱',
`description` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',
`admin_count` int(11) NULL DEFAULT NULL COMMENT '后臺用戶數(shù)量',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '創(chuàng)建時間'
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用戶角色表' ROW_FORMAT = Dynamic;
permission表sql
DROP TABLE IF EXISTS `permission`;
CREATE TABLE `permission` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`pid` bigint(20) NULL DEFAULT NULL COMMENT '父級權限id',
`name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '名稱',
`value` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '權限值',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '創(chuàng)建時間'
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 19 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用戶權限表' ROW_FORMAT = Dynamic;
admin_permission_relation表sql
DROP TABLE IF EXISTS `admin_permission_relation`;
CREATE TABLE `admin_permission_relation` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`admin_id` bigint(20) NULL DEFAULT NULL,
`permission_id` bigint(20) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用戶和權限關系表' ROW_FORMAT = Dynamic;
admin_role_relation表sql
DROP TABLE IF EXISTS `admin_role_relation`;
CREATE TABLE `admin_role_relation` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`admin_id` bigint(20) NULL DEFAULT NULL,
`role_id` bigint(20) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用戶和角色關系表' ROW_FORMAT = Dynamic;
role_permission_relation表sql
DROP TABLE IF EXISTS `role_permission_relation`;
CREATE TABLE `role_permission_relation` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`role_id` bigint(20) NULL DEFAULT NULL,
`permission_id` bigint(20) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 18 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用戶角色和權限關系表' ROW_FORMAT = Dynamic;
1 . pom導入依賴
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--SpringSecurity依賴配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis 生成器 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.7</version>
</dependency>
<!--MyBatis分頁插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.10</version>
</dependency>
<!--集成druid連接池-->
<!--web監(jiān)控 http://127.0.0.1:8080/druid/index.html -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!--Mysql數(shù)據(jù)庫驅動-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--Swagger-UI API文檔生產工具-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!--Hutool Java工具包-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.4.7</version>
</dependency>
<!--JWT(Json Web Token)登錄支持-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!--參數(shù)校驗 javax.validation.constraints-->
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.5.Final</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
</dependencies>
2. application配置
server:
port: 8080
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/testmall?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: 123456
redis:
# redis服務器地址
host: localhost
# redis數(shù)據(jù)庫索引(默認為0)
database: 0
# redis服務器連接端口
port: 6379
# redis 服務器連接密碼 默認為空
password:
jedis:
pool:
# 連接池最大連接數(shù)(使用負值表示沒有限制)
max-active: 8
# 連接池最大阻塞等待時間(使用負值表示沒有限制)
max-wait: -1ms
# 連接池中的最大空閑連接
max-idle: 8
# 連接池中的最小空閑連接
min-idle: 0
# 連接超時時間(毫秒)
timeout: 3000ms
# 自定義 redis key
redis:
# 自定義 redis key
key:
prefix:
authCode: "portal:authCode:"
expire:
#驗證碼超期時間
authCode: 120
#自定義字段
jwt:
secret: mySecret
# jwt超期限時間 60*60*24
expiration: 604800
# JWT存儲的請求頭
tokenHeader: Authorization
# JWT負載中拿到開頭
tokenHead: Bearer
#mybatis
mybatis:
#mapper 映射文件地址
mapper-locations:
- classpath:mapper/*.xml
- classpath:com/**/mapper/*.xml
- security 配置
/**
* SpringSecurity的配置
*
* UserDetails:SpringSecurity定義用于封裝用戶信息的類(主要是用戶信息和權限),
* 需要自行實現(xiàn);
*/
@Configuration
//開啟Security
@EnableWebSecurity
//保證post之前的注解可以使用
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UmsAdminService adminService;
@Autowired
private RestfulAccessDeniedHandler restfulAccessDeniedHandler;
@Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
/**
* 用于配置需要攔截的url路徑、jwt過濾器及出異常后的處理器;
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
//由于使用的是JWT,我們這里不需要csrf
.disable()//
//基于token,所以不需要session
.sessionManagement()
//STATELESS不創(chuàng)建httpsession并不使用
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)//
.and()
.authorizeRequests()
//允許對于網(wǎng)站靜態(tài)資源的無授權訪問
.antMatchers(HttpMethod.GET,
"/",
"/*.html",
"/favicon.ico",
"/**/*.html",
"/**/*.css",
"/**/*.js",
"/swagger-resources/**",
"/v2/api-docs")
.permitAll()
//對登錄注冊要允許匿名訪問
.antMatchers("/admin/login",
"/admin/register")
.permitAll()
//跨域請求會先進行一次options請求
.antMatchers(HttpMethod.OPTIONS)
.permitAll()
//測試時全部運行訪問
// .antMatchers("/**")
// .permitAll()
//除上面外的所有請求全部需要鑒權認證
.anyRequest()
.authenticated();
//禁用緩存
http.headers().cacheControl();
//添加JWT filter 前置攔截
http.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
//添加自定義未授權和未登錄結果返回
http.exceptionHandling().accessDeniedHandler(restfulAccessDeniedHandler)
.authenticationEntryPoint(restAuthenticationEntryPoint);
}
/**
* 用于配置 UserDetailsService 及PasswordEncoder;
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService())
.passwordEncoder(passwordEncoder());
}
/**
* SpringSecurity定義的用于對密碼進行編碼及比對的接口,
* 目前使用的是BCryptPasswordEncoder;
* @return
*/
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
/**
* SpringSecurity定義的核心接口,用于根據(jù)用戶名獲取用戶信息,需要自行實現(xiàn);
* @return
*/
@Bean
public UserDetailsService userDetailsService(){
//獲取登錄用戶信息,查詢用戶權限
// return username -> {
// UmsAdmin admin = adminService.getAdminByUsername(username);
// if (admin !=null ){
// List<UmsPermission> permissionList = adminService.getPermissionList(admin.getId());
// return new AdminUserDetails(admin,permissionList);
// }
// throw new UsernameNotFoundException("用戶名或密碼錯誤");
// };
return new UserDetailsServiceImpl();
}
/**
* 在用戶名和密碼校驗前添加的過濾器,
* 如果有jwt的token,會自行根據(jù)token信息進行登錄。
* @return
*/
@Bean
public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter(){
return new JwtAuthenticationTokenFilter();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
攔截器
JwtAuthenticationTokenFilter
/**
* JWT登錄授權過濾器
* 在用戶名和密碼校驗前添加的過濾器,如果請求中有jwt的token且有效,
* 會取出token中的用戶名,然后調用SpringSecurity的API進行登錄操作。
* 請求 前置 過濾 token
*/
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
private static final Logger LOGGER =LoggerFactory.getLogger(JwtAuthenticationTokenFilter.class);
@Autowired
private UmsAdminService umsAdminService;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Value("${jwt.tokenHeader}")
private String tokenHeader;
@Value("${jwt.tokenHead}")
private String tokenHead;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String authHeader = request.getHeader(this.tokenHeader);
LOGGER.info("checking authHeader:{}",authHeader);
if (authHeader != null && authHeader.startsWith(this.tokenHead)){
//The part after "Bearer "
String authToken = authHeader.substring(this.tokenHead.length());
LOGGER.info("checking authToken:{}",authToken);
String username = jwtTokenUtil.getUserNameFromToken(authToken);
LOGGER.info("checking username:{}",username);
//SecurityContextHolder.getContext().getAuthentication() == null
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
//
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
LOGGER.info("authenticated user:{}", username);
//打印用戶的權限
LOGGER.info("authenticated Authorities:{}", userDetails.getAuthorities().size());
//這個需要設置
//如果沒有這個會報 :Full authentication is required to access this resource
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
filterChain.doFilter(request,response);
}
}
RestAuthenticationEntryPoint
/**
* 當未登錄或者token失效訪問接口時,自定義的返回結果
*/
@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
private static final Logger LOGGER = LoggerFactory.getLogger(RestAuthenticationEntryPoint.class);
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException e) throws IOException, ServletException {
LOGGER.info("RestAuthenticationEntryPoint commence 未登錄或者token失效訪問接口");
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
response.getWriter().println(JSONUtil.parse(CommonResult.unauthorized(e.getMessage())));
response.getWriter().flush();
}
}
RestfulAccessDeniedHandler
/**
* 當訪問接口沒有權限時,自定義的返回結果
*
*/
@Component
public class RestfulAccessDeniedHandler implements AccessDeniedHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(RestfulAccessDeniedHandler.class);
@Override
public void handle(HttpServletRequest request,
HttpServletResponse response,
AccessDeniedException e) throws IOException, ServletException {
LOGGER.info("RestfulAccessDeniedHandler handle 當訪問接口沒有權限時,自定義的返回結果");
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
//沒有訪問權限
response.getWriter().println(JSONUtil.parse(CommonResult.failed(e.getMessage())));
response.getWriter().flush();
}
}
service
UmsAdminService
/**
*
*/
public interface UmsAdminService {
//根據(jù)用戶名獲取后臺管理員
UmsAdmin getAdminByUsername(String username);
//注冊功能
UmsAdmin register(UmsAdmin umsAdminParam);
/**
* 登錄功能
* @param username
* @param password
* @return 生成的JWT的token
*/
String login(String username,String password);
//獲取用戶所有權限(包括角色權限和+-權限)
List<UmsPermission> getPermissionList(Long adminId);
}
UmsAdminServiceImpl
/**
*UmsAdminService實現(xiàn)類
*/
@Service
public class UmsAdminServiceImpl implements UmsAdminService {
private static final Logger LOGGER = LoggerFactory.getLogger(UmsAdminServiceImpl.class);
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private PasswordEncoder passwordEncoder;
@Value("${jwt.tokenHead}")
private String tokenHead;
@Autowired
private UmsAdminMapper adminMapper;
@Autowired
private UmsAdminRoleRelationDao adminRoleRelationDao;
//通過用戶名獲取管理員信息
@Override
public UmsAdmin getAdminByUsername(String username) {
UmsAdminExample example = new UmsAdminExample();
example.createCriteria().andUsernameEqualTo(username);
List<UmsAdmin> adminList = adminMapper.selectByExample(example);
if (adminList != null && adminList.size()>0){
return adminList.get(0);
}
return null;
}
@Override
public UmsAdmin register(UmsAdmin umsAdminParam) {
UmsAdmin umsAdmin = new UmsAdmin();
BeanUtils.copyProperties(umsAdminParam,umsAdmin);
umsAdmin.setCreateTime(new Date());
umsAdmin.setStatus(1);
//查詢是否有相同用戶名的用戶
UmsAdminExample example = new UmsAdminExample();
example.createCriteria().andUsernameEqualTo(umsAdmin.getUsername());
List<UmsAdmin> umsAdminList = adminMapper.selectByExample(example);
if (umsAdminList.size()>0){
return null;
}
//將密碼進行加密操作
String encodePassword = passwordEncoder.encode(umsAdmin.getPassword());
umsAdmin.setPassword(encodePassword);
adminMapper.insert(umsAdmin);
return umsAdmin;
}
@Override
public String login(String username, String password) {
String token = null;
try {
AdminUserDetails userDetails = null;
List<UmsPermission> permissionList=null;
//獲取用戶的信息
UmsAdmin admin = getAdminByUsername(username);
if (admin==null){
throw new BadCredentialsException("用戶不存在");
}
permissionList = getPermissionList(admin.getId());
userDetails = new AdminUserDetails(admin,permissionList);
if (!passwordEncoder.matches(password,userDetails.getPassword())){
throw new BadCredentialsException("密碼不正確");
}
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());
// //避免跨多個線程的競爭條件
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
token = jwtTokenUtil.generateToken(admin);
// UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// if (!passwordEncoder.matches(password, userDetails.getPassword())) {
// throw new BadCredentialsException("密碼不正確");
// }
// UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
// SecurityContextHolder.getContext().setAuthentication(authentication);
// token = jwtTokenUtil.generateToken(userDetails);
}catch (AuthenticationException e){
LOGGER.warn("登錄異常:{}",e.getMessage());
}
return token;
}
@Override
public List<UmsPermission> getPermissionList(Long id) {
return adminRoleRelationDao.getPermissionList(id);
}
}
UserDetailsServiceImpl
/**
* UserDetailsService 實現(xiàn) 返回權限查詢
*/
public class UserDetailsServiceImpl implements UserDetailsService {
private static final Logger logger = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
@Autowired
private UmsAdminService umsAdminService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UmsAdmin admin = umsAdminService.getAdminByUsername(username);
if (admin !=null ){
List<UmsPermission> permissionList = umsAdminService.getPermissionList(admin.getId());
return new AdminUserDetails(admin,permissionList);
}
throw new UsernameNotFoundException("用戶名或密碼錯誤");
}
}
/**
* 用戶與角色管理自定義Dao
* mapper映射
*/
public interface UmsAdminRoleRelationDao {
//獲取用戶所有權限(包括+-權限)
public List<UmsPermission> getPermissionList(@Param("adminId") Long adminId);
}
UmsAdminRoleRelationDao.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mall.tiny04.dao.UmsAdminRoleRelationDao">
<select id="getPermissionList" resultMap="com.mall.tiny04.mbg.mapper.UmsPermissionMapper.BaseResultMap">
SELECT
p.*
FROM
admin_role_relation ar
LEFT JOIN role r ON ar.role_id = r.id
LEFT JOIN role_permission_relation rp ON r.id = rp.role_id
LEFT JOIN permission p ON rp.permission_id = p.id
WHERE
ar.admin_id = #{adminId}
AND p.id IS NOT NULL
AND p.id NOT IN (
SELECT
p.id
FROM
admin_permission_relation pr
LEFT JOIN permission p ON pr.permission_id = p.id
WHERE
pr.type = - 1
AND pr.admin_id = #{adminId}
)
UNION
SELECT
p.*
FROM
admin_permission_relation pr
LEFT JOIN permission p ON pr.permission_id = p.id
WHERE
pr.type = 1
AND pr.admin_id = #{adminId}
</select>
</mapper>
controller方法上添加權限

@PostMapping("/update/{id}")
// id 是否有 update權限
@PreAuthorize("hasPermission(#id,'update')")
//是否有創(chuàng)建權限
//@PreAuthorize("hasAuthority('create')")
// 是否有admin權限
// @PreAuthorize("hasRole('admin')")
@ResponseBody
public CommonResult updateBrand(@PathVariable("id") Long id,
@RequestBody PmsBrand pmsBrand,
BindingResult result){
}