可以做公众号背景图的网站,大图做网站背景加载慢,wordpress tag 别名,徐州网页公司目录 权限系统的必要性常见的权限管理框架SpringSecurity授权基本流程准备脚本限制访问资源所需权限菜单实体类和Mapper封装权限信息封装认证/鉴权失败处理认证失败封装鉴权失败封装配置SpringSecurity 过滤器跨域处理接口添加鉴权hasAuthority/hasAnyAuthorityhasRole/ hasA… 目录 权限系统的必要性常见的权限管理框架SpringSecurity授权基本流程准备脚本限制访问资源所需权限菜单实体类和Mapper封装权限信息封装认证/鉴权失败处理认证失败封装鉴权失败封装配置SpringSecurity 过滤器跨域处理接口添加鉴权hasAuthority/hasAnyAuthorityhasRole/ hasAnyRole 自定义权限校验方法 权限系统的必要性
权限系统在现代软件开发、信息管理系统、网络服务和各种数字平台中扮演着至关重要的角色其必要性主要体现在以下几个方面 安全控制权限系统是保护数据和资源安全的第一道防线。通过限制对敏感信息和关键功能的访问可以有效防止未经授权的访问、修改或泄露从而降低安全风险。 职责分离在组织内部不同的用户或角色拥有不同的职责。权限系统确保每个用户只能访问和操作与他们的工作职责相关的系统部分这有助于实现职责分离和内部控制减少错误和欺诈的可能性。 合规性要求许多行业都有严格的数据保护法规和标准如GDPR、HIPAA等要求对个人信息和敏感数据进行严格的访问控制。权限系统帮助组织符合这些法律法规的要求避免法律风险和罚款。 提升用户体验通过为不同用户提供定制化的界面和功能权限系统可以减少信息过载使用户更容易找到他们需要的信息和服务从而提升整体的用户体验。 审计追踪权限系统能够记录用户的访问和操作日志这对于事后审计、故障排查和安全事件调查至关重要。这不仅有助于及时发现并解决问题也为追究责任提供了依据。 灵活性和可扩展性随着组织的发展和需求的变化权限系统允许管理员灵活地调整权限设置新增或删除用户角色以及对系统功能进行细粒度的控制保证了系统的长期稳定性和可扩展性。
总之权限系统是维护信息安全、支持组织管理和满足法律法规要求的基础架构对于保障数字环境的稳定、安全和高效运行具有不可替代的作用。
常见的权限管理框架
Java Web开发中为了实现权限管理开发者常采用一些成熟的权限框架来简化开发流程和提高系统安全性。以下是一些常见的Java权限管理框架 Spring Security这是Java领域中最受欢迎和广泛使用的安全框架之一它为Web应用程序提供了一整套安全解决方案包括认证Authentication和授权Authorization。Spring Security支持多种认证机制如JWT、OAuth2、自定义权限控制并且能够无缝集成到Spring Boot应用中。 Apache ShiroShiro是一个强大且易用的安全框架它提供身份验证、授权、会话管理以及加密等功能。相比Spring SecurityShiro的学习曲线更平缓适用于需要快速实现安全功能的项目。Shiro支持多种环境不仅限于Web应用也适用于命令行应用、Swing应用等。 JBoss KeycloakKeycloak是一个开源的Identity and Access Management (IAM)系统提供了单一登录SSO、身份管理、社交登录等特性。它可以通过OpenID Connect、OAuth 2.0等协议与Java Web应用集成非常适合构建大型分布式系统的权限管理。 Spring Authorization Server这是Spring生态系统中用于构建授权服务器的新项目特别适合需要实现OAuth2协议的场景。虽然它本身不直接处理应用程序的权限控制逻辑但与Spring Security结合使用可以构建出强大的认证和授权体系。 Apache Ranger虽然更多被用于大数据平台如Hadoop、Hive、Kafka的权限管理但Apache Ranger也可以应用于其他Java Web项目中特别是那些需要复杂数据权限控制的场景。
选择合适的权限框架时需要根据项目的具体需求、团队熟悉度、系统规模以及是否需要支持特定的安全协议等因素综合考虑。
SpringSecurity授权
基本流程
SpringSecurity是使用默认的FilterSecurityInterceptor来进行权限校验。在FilterSecurityInterceptor中会从SecurityContextHolder获取其中的Authentication然后获取其中的权限信息。并以此来判断当前用户是否拥有访问当前资源所需的权限。因此需要把用户成功登录后的的权限信息也存入Authentication 然后设置资源所需要的权限即可。
准备脚本
/*Navicat Premium Data TransferSource Server : 本机连接Source Server Type : MySQLSource Server Version : 50744Source Host : localhost:3306Source Schema : kgc_powerTarget Server Type : MySQLTarget Server Version : 50744File Encoding : 65001Date: 24/06/2024 15:07:37
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS 0;-- ----------------------------
-- Table structure for account
-- ----------------------------
DROP TABLE IF EXISTS account;
CREATE TABLE account (id int(11) NOT NULL,accountCode varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,accountName varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,accountPassword varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,PRIMARY KEY (id) USING BTREE
) ENGINE InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci ROW_FORMAT Dynamic;-- ----------------------------
-- Records of account
-- ----------------------------
INSERT INTO account VALUES (1, admin, 系统管理员, $2a$10$dJ1Ct/QuOOJTkhNkYeFh8uCeEqpVUO.ZjiPOfPsmbsWlX3ZIp.kDa);
INSERT INTO account VALUES (2, zhangsan, 张三, $2a$10$dJ1Ct/QuOOJTkhNkYeFh8uCeEqpVUO.ZjiPOfPsmbsWlX3ZIp.kDa);
INSERT INTO account VALUES (3, lisi, 李四, $2a$10$dJ1Ct/QuOOJTkhNkYeFh8uCeEqpVUO.ZjiPOfPsmbsWlX3ZIp.kDa);
INSERT INTO account VALUES (4, wangwu, 王五, $2a$10$dJ1Ct/QuOOJTkhNkYeFh8uCeEqpVUO.ZjiPOfPsmbsWlX3ZIp.kDa);
INSERT INTO account VALUES (5, zhaoliu, 赵六, $2a$10$dJ1Ct/QuOOJTkhNkYeFh8uCeEqpVUO.ZjiPOfPsmbsWlX3ZIp.kDa);-- ----------------------------
-- Table structure for account_role
-- ----------------------------
DROP TABLE IF EXISTS account_role;
CREATE TABLE account_role (accountId bigint(200) NOT NULL AUTO_INCREMENT COMMENT 用户id,roleId bigint(200) NOT NULL DEFAULT 0 COMMENT 角色id,PRIMARY KEY (accountId, roleId) USING BTREE
) ENGINE InnoDB AUTO_INCREMENT 6 CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci ROW_FORMAT Dynamic;-- ----------------------------
-- Records of account_role
-- ----------------------------
INSERT INTO account_role VALUES (1, 1);
INSERT INTO account_role VALUES (2, 2);
INSERT INTO account_role VALUES (3, 2);
INSERT INTO account_role VALUES (4, 3);
INSERT INTO account_role VALUES (5, 3);-- ----------------------------
-- Table structure for menu
-- ----------------------------
DROP TABLE IF EXISTS menu;
CREATE TABLE menu (id bigint(20) NOT NULL AUTO_INCREMENT,menuName varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT NULL COMMENT 菜单名,path varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 路由地址,component varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 组件路径,visible char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 0 COMMENT 菜单状态0显示 1隐藏,status char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 0 COMMENT 菜单状态0正常 1停用,perms varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 权限标识,icon varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT # COMMENT 菜单图标,createBy bigint(20) NULL DEFAULT NULL,createTime datetime NULL DEFAULT NULL,updateBy bigint(20) NULL DEFAULT NULL,updateTime datetime NULL DEFAULT NULL,delFlag int(11) NULL DEFAULT 0 COMMENT 是否删除0未删除 1已删除,remark varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 备注,PRIMARY KEY (id) USING BTREE
) ENGINE InnoDB AUTO_INCREMENT 5 CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 菜单表 ROW_FORMAT Dynamic;-- ----------------------------
-- Records of menu
-- ----------------------------
INSERT INTO menu VALUES (1, 订单管理, /order, /order, 0, 0, system:order, #, NULL, NULL, NULL, NULL, 0, NULL);
INSERT INTO menu VALUES (2, 系统管理, /sys, /sys, 0, 0, system:sys, #, NULL, NULL, NULL, NULL, 0, NULL);
INSERT INTO menu VALUES (3, 个人中心, /info, /info, 0, 0, system:info, #, NULL, NULL, NULL, NULL, 0, NULL);
INSERT INTO menu VALUES (4, 商品管理, /product, /product, 0, 0, system:product, #, NULL, NULL, NULL, NULL, 0, NULL);-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS role;
CREATE TABLE role (id bigint(20) NOT NULL AUTO_INCREMENT,name varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,roleKey varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 角色权限字符串,status char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 0 COMMENT 角色状态0正常 1停用,delFlag int(1) NULL DEFAULT 0 COMMENT del_flag,createBy bigint(200) NULL DEFAULT NULL,createTime datetime NULL DEFAULT NULL,updateBy bigint(200) NULL DEFAULT NULL,updateTime datetime NULL DEFAULT NULL,remark varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 备注,PRIMARY KEY (id) USING BTREE
) ENGINE InnoDB AUTO_INCREMENT 4 CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 角色表 ROW_FORMAT Dynamic;-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO role VALUES (1, 系统管理员, ADMIN, 0, 0, NULL, NULL, NULL, NULL, NULL);
INSERT INTO role VALUES (2, 供应商, PROVIDER, 0, 0, NULL, NULL, NULL, NULL, NULL);
INSERT INTO role VALUES (3, 需求方, CONSUMER, 0, 0, NULL, NULL, NULL, NULL, NULL);-- ----------------------------
-- Table structure for role_menu
-- ----------------------------
DROP TABLE IF EXISTS role_menu;
CREATE TABLE role_menu (roleId bigint(200) NOT NULL AUTO_INCREMENT COMMENT 角色ID,menuId bigint(200) NOT NULL DEFAULT 0 COMMENT 菜单id,PRIMARY KEY (roleId, menuId) USING BTREE
) ENGINE InnoDB AUTO_INCREMENT 4 CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci ROW_FORMAT Dynamic;-- ----------------------------
-- Records of role_menu
-- ----------------------------
INSERT INTO role_menu VALUES (1, 2);
INSERT INTO role_menu VALUES (1, 3);
INSERT INTO role_menu VALUES (2, 1);
INSERT INTO role_menu VALUES (2, 3);
INSERT INTO role_menu VALUES (3, 1);
INSERT INTO role_menu VALUES (3, 3);
INSERT INTO role_menu VALUES (3, 4);SET FOREIGN_KEY_CHECKS 1;限制访问资源所需权限
SpringSecurity提供了基于注解的权限控制方案可以使用注解去指定访问对应的资源所需的权限 但是要使用它需要先开启相关配置。启动类上加EnableGlobalMethodSecurity(prePostEnabled true)
菜单实体类和Mapper
package com.micro.pojo;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;/*** author: zjl* datetime: 2024/6/24* desc: 复兴Java我辈义不容辞*/
Data
public class Menu implements Serializable {private Long id;/*** 菜单名*/private String menuName;/*** 路由地址*/private String path;/*** 组件路径*/private String component;/*** 菜单状态0显示 1隐藏*/private String visible;/*** 菜单状态0正常 1停用*/private String status;/*** 权限标识*/private String perms;/*** 菜单图标*/private String icon;private Long createBy;private Date createTime;private Long updateBy;private Date updateTime;/*** 是否删除0未删除 1已删除*/private Integer delFlag;/*** 备注*/private String remark;
}ListString selectPermsByAccountId(Integer accountId);select idselectPermsByAccountId resultTypestring parameterTypeintSELECTDISTINCT M.PERMSFROMACCOUNT_ROLE ARLEFT JOIN ROLE R ON AR.ROLEID R.IDLEFT JOIN ROLE_MENU RM ON AR.ROLEID RM.ROLEIDLEFT JOIN MENU M ON M.ID RM.MENUIDWHEREACCOUNTID #{accountId}AND R.STATUS 0AND M.STATUS 0/selectmybatis:mapper-locations: classpath:mapper/*.xmlconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl封装权限信息
在UserDetailsServiceImpl中去调用该mapper的方法查询权限信息封装到LoginUser对象中
Service
public class AccountDetailsServiceImpl implements UserDetailsService {Resourceprivate AccountMapper accountMapper;Resourceprivate MenuMapper menuMapper;Overridepublic UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {Account account accountMapper.selectAccountByAccountCode(userName);if(Objects.isNull(account)){throw new RuntimeException(用户名或密码错误);}//根据用户查询权限信息 LoginAccountListString permissionKeyList menuMapper.selectPermsByAccountId(account.getId());//封装成UserDetails对象返回return new LoginAccount(account, permissionKeyList);}
}package com.micro.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;/*** author: zjl* datetime: 2024/6/22* desc: 复兴Java我辈义不容辞*/
Data
NoArgsConstructor
public class LoginAccount implements UserDetails {private Account account;private ListString permissions;JSONField(serialize false)private ListGrantedAuthority authorities;public LoginAccount(Account account,ListString permissions) {this.account account;this.permissions permissions;}Overridepublic Collection? extends GrantedAuthority getAuthorities() {if(authorities!null){return authorities;}//把permissions中字符串类型的权限信息转换成GrantedAuthority对象存入authorities中authorities permissions.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());return authorities;}Overridepublic String getPassword() {return account.getAccountPassword();}Overridepublic String getUsername() {return account.getAccountName();}Overridepublic boolean isAccountNonExpired() {return true;}Overridepublic boolean isAccountNonLocked() {return true;}Overridepublic boolean isCredentialsNonExpired() {return true;}Overridepublic boolean isEnabled() {return true;}
}封装认证/鉴权失败处理
在SpringSecurity中如果在认证或者授权的过程中出现了异常会被ExceptionTranslationFilter捕获到。在ExceptionTranslationFilter中会去判断是认证失败还是授权失败出现的异常。 认证过程中出现的异常可以被封装成AuthenticationException然后调用AuthenticationEntryPoint 对象的方法去进行异常处理。如果是授权过程中出现的异常可以被封装成AccessDeniedException然后调用AccessDeniedHandler对象的方法去进行异常处理。
认证失败封装
package com.micro.service;import com.alibaba.fastjson.JSON;
import com.micro.utils.ResponseResult;
import com.micro.utils.WebUtils;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** author: zjl* datetime: 2024/6/24* desc: 复兴Java我辈义不容辞*/Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {ResponseResult result new ResponseResult(HttpStatus.UNAUTHORIZED.value(), 认证失败请重新登录);String json JSON.toJSONString(result);WebUtils.renderString(response,json);}
}鉴权失败封装
package com.micro.service;import com.alibaba.fastjson.JSON;
import com.micro.utils.ResponseResult;
import com.micro.utils.WebUtils;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** author: zjl* datetime: 2024/6/24* desc: 复兴Java我辈义不容辞*/
Component
public class AccessDeniedHandlerImpl implements AccessDeniedHandler {Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {ResponseResult result new ResponseResult(HttpStatus.FORBIDDEN.value(), 权限不足);String json JSON.toJSONString(result);WebUtils.renderString(response,json);}
}配置SpringSecurity
package com.micro.config;import com.micro.filter.JwtAuthenticationTokenFilter;
import com.micro.service.AccessDeniedHandlerImpl;
import com.micro.service.AuthenticationEntryPointImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;import javax.annotation.Resource;/*** author: zjl* datetime: 2024/6/22* desc: 复兴Java我辈义不容辞*/Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {Resourceprivate JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;Resourceprivate AccessDeniedHandlerImpl accessDeniedHandler;Resourceprivate AuthenticationEntryPointImpl authenticationEntryPoint;Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}Overrideprotected void configure(HttpSecurity http) throws Exception {http//关闭csrf.csrf().disable()//不通过Session获取SecurityContext.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()// 对于登录接口 允许匿名访问.antMatchers(/login).anonymous()// 除上面外的所有请求全部需要鉴权认证.anyRequest().authenticated();//把token校验过滤器添加到过滤器链中http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).accessDeniedHandler(accessDeniedHandler);}BeanOverridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}
}过滤器
package com.micro.filter;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.micro.pojo.Account;
import com.micro.pojo.LoginAccount;
import com.micro.utils.JwtUtil;
import com.micro.utils.RedisStringUtil;
import io.jsonwebtoken.Claims;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Objects;/*** author: zjl* datetime: 2024/6/22* desc: 复兴Java我辈义不容辞*/
Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {Resourceprivate RedisStringUtil redisStringUtil;Resourceprivate ObjectMapper objectMapper;Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {//获取tokenString token request.getHeader(token);if (!StringUtils.hasText(token)) {//放行filterChain.doFilter(request, response);return;}//解析tokenString userid;try {Claims claims JwtUtil.parseJWT(token);userid claims.getSubject();} catch (Exception e) {e.printStackTrace();throw new RuntimeException(token非法);}//从redis中获取用户信息String redisKey login: userid;LoginAccount loginAccount JSON.parseObject(redisStringUtil.get(redisKey), LoginAccount.class);if(Objects.isNull(loginAccount)){throw new RuntimeException(用户未登录);}//存入SecurityContextHolder//获取权限信息封装到Authentication中UsernamePasswordAuthenticationToken authenticationToken new UsernamePasswordAuthenticationToken(loginAccount,null,loginAccount.getAuthorities());SecurityContextHolder.getContext().setAuthentication(authenticationToken);//放行filterChain.doFilter(request, response);}
}跨域处理
package com.micro.config;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** author: zjl* datetime: 2024/6/24* desc: 复兴Java我辈义不容辞*/
Configuration
public class CorsConfig implements WebMvcConfigurer {Overridepublic void addCorsMappings(CorsRegistry registry) {// 设置允许跨域的路径registry.addMapping(/**)// 设置允许跨域请求的域名.allowedOrigins(*)// 是否允许cookie.allowCredentials(true)// 设置允许的请求方式.allowedMethods(GET, POST, DELETE, PUT)// 设置允许的header属性.allowedHeaders(*)// 跨域允许时间.maxAge(60 * 60);}
}SecurityConfig类中configure()方法添加以下代码
//允许跨域http.cors();接口添加鉴权
SpringSecurity提供了以下方法hasAuthorityhasAnyAuthorityhasRolehasAnyRole等。
hasAuthority/hasAnyAuthority
hasAuthority方法内部调用authentication的getAuthorities方法获取用户的权限列表。然后判断存入的方法参数数据在权限列表中。 hasAnyAuthority方法可以传入多个权限只有用户有其中任意一个权限都可以访问对应资源。
RestController
RequestMapping(/order)
public class OrderController {GetMapping(/list)//PreAuthorize(hasAnyAuthority(system:aaa,system:bbb,system:order))PreAuthorize(hasAuthority(system:order))public ResponseResult list(){return new ResponseResult(200, 订单列表);}
}hasRole/ hasAnyRole
hasRole要求有对应的角色才可以访问但是它内部会把传入的参数拼接上 ROLE_ 后再去比较。所以这种情况下要用用户对应的权限也要有 ROLE_ 这个前缀才可以。hasAnyRole 有任意的角色就可以访问。它内部也会把传入的参数拼接上 ROLE_ 后再去比较。所以这种情况下要用用户对应的权限也要有 ROLE_ 这个前缀才可以。
修改数据库 GetMapping(/list)//PreAuthorize(hasAnyAuthority(system:aaa,system:bbb,system:order))//PreAuthorize(hasAuthority(system:order))PreAuthorize(hasRole(system:order))public ResponseResult list(){return new ResponseResult(200, 订单列表);}自定义权限校验方法
Component(ex)
public class KgcExpressionRoot {public boolean hasAuthority(String authority){//获取当前用户的权限Authentication authentication SecurityContextHolder.getContext().getAuthentication();LoginAccount loginAccount (LoginAccount) authentication.getPrincipal();ListString permissions loginAccount.getPermissions();//判断用户权限集合中是否存在authorityreturn permissions.contains(authority);}
} 在SPEL表达式中使用 ex相当于获取容器中bean的名字未ex的对象。然后再调用这个对象的hasAuthority方法 GetMapping(/list)//PreAuthorize(hasAnyAuthority(system:aaa,system:bbb,system:order))//PreAuthorize(hasAuthority(system:order))//PreAuthorize(hasRole(system:order))PreAuthorize(ex.hasAuthority(system:order))public ResponseResult list(){return new ResponseResult(200, 订单列表);}