当前位置: 首页 > news >正文

怎样做网站代理云开发控制台

怎样做网站代理,云开发控制台,推荐几个安全免费的网站,如何建立外贸网站目录 参考一、概念SpEL表达式 二、开发引入包定义注解定义切面定义用户上下文 三、测试新建Service在方法上注解新建Service在类上注解运行 参考 SpringBoot:SpEL让复杂权限控制变得很简单 一、概念 对于在Springboot中,利用自定义注解切面来实现接口…

目录

  • 参考
  • 一、概念
    • SpEL表达式
  • 二、开发
    • 引入包
    • 定义注解
    • 定义切面
    • 定义用户上下文
  • 三、测试
    • 新建Service在方法上注解
    • 新建Service在类上注解
    • 运行

参考

SpringBoot:SpEL让复杂权限控制变得很简单

一、概念

对于在Springboot中,利用自定义注解+切面来实现接口权限的控制这个大家应该都很熟悉,也有大量的博客来介绍整个的实现过程,整体来说思路如下:

  • 自定义一个权限校验的注解,包含参数value
  • 配置在对应的接口上
  • 定义一个切面类,指定切点
  • 在切入的方法体里写上权限判断的逻辑

SpEL表达式

本文前面提到SpEL,那么到底SpEL是啥呢? SpEL的全称为Spring Expression Language,即Spring表达式语言。是Spring3.0提供的。他最强大的功能是可以通过运行期间执行的表达式将值装配到我们的属性或构造函数之中。如果有小伙伴之前没有接触过,不太理解这句话的含义,那么不要紧,继续往下看,通过后续的实践你就能明白他的作用了。

二、开发

引入包

  	<!--spring aop + aspectj--><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.0.8.RELEASE</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.8.9</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.9</version></dependency><!--spring aop + aspectj-->

定义注解

我们仅需要定义一个value属性用于接收表达式即可。


@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PreAuth {/***** permissionAll()-----只要配置了角色就可以访问* hasPermission("MENU.QUERY")-----有MENU.QUERY操作权限的角色可以访问* hasAnyPermission("MENU.QUERY","MENU.ADD")-----有MENU.QUERY操作权限的角色可以访问* permitAll()-----放行所有请求* denyAll()-----只有超级管理员角色才可访问* hasAuth()-----只有登录后才可访问* hasTimeAuth(1,,10)-----只有在1-10点间访问* hasRole(‘管理员’)-----具有管理员角色的人才能访问* hasAnyRole(‘管理员’,'总工程师')-----同时具有管理员* hasAllRole(‘管理员’,'总工程师')-----同时具有管理员、总工程师角色的人才能访问、总工程师角色的人才能访问** Spring el* 文档地址:<a href="https://docs.spring.io/spring/docs/5.1.6.RELEASE/spring-framework-reference/core.html#expressions">...</a>*/String value();}

定义切面

我们就需要定义切面了。这里要考虑一个点。我们希望的是如果方法上有注解,则对方法进行限制,若方法上无注解,单是类上有注解,那么类上的权限注解对该类下所有的接口生效。因此,我们切点的话要用@within注解

// 方式一
@Pointcut(value = "execution(* com.edevp.spring.spel.auth..*.*(..))")
// 方式二 直接切入注解
@Pointcut("@annotation(com.edevp.spring.spel.auth.annotation.PreAuth) || @within(com.edevp.spring.spel.auth.annotation.PreAuth)")

/***  必须的注解* @create 2023/5/24*/
@Component
@Aspect
@Slf4j
public class AuthAspect {@Resourceprivate AuthContext authContext;@PostConstructpublic void init(){log.info("鉴权切面初始化");}/*** Spel解析器 关键点来了。这里我们要引入SpEL。*/private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();//    @Pointcut(value = "execution(* com.edevp.spring.spel.auth..*.*(..))")@Pointcut("@annotation(com.edevp.spring.spel.auth.annotation.PreAuth) || @within(com.edevp.spring.spel.auth.annotation.PreAuth)")private void beforePointcut(){//切面,方法里的内容不会执行}/*** 前置通知* @param joinPoint 切点*/@Before(value = "beforePointcut()")public void before(JoinPoint joinPoint){//@Before是在方法执行前无法终止原方法执行log.info("前置通知。。。"+joinPoint);if (handleAuth(joinPoint)) {return;}throw new NoAuthException("没权限");}/*** 环绕通知* @param joinPoint 切点* @return Object*/@Around("beforePointcut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {//@Before是在方法执行前无法终止原方法执行log.info("环绕通知。。。"+joinPoint);return joinPoint.proceed();}/*** 判断是否有权限* @param point 切点* @return boolean*/@SuppressWarnings("unchecked")private boolean handleAuth(JoinPoint point) {MethodSignature ms = point.getSignature() instanceof MethodSignature? (MethodSignature) point.getSignature():null;assert ms != null;Method method = ms.getMethod();// 读取权限注解,优先方法上,没有则读取类PreAuth preAuth = method.getAnnotation(PreAuth.class);if(preAuth == null){preAuth = (PreAuth) ms.getDeclaringType().getDeclaredAnnotation(PreAuth.class);}// 判断表达式String condition = preAuth.value();if (StringUtil.isNotBlank(condition)) {Expression expression = EXPRESSION_PARSER.parseExpression(condition);StandardEvaluationContext context = new StandardEvaluationContext(authContext);// 获取解析计算的结果return Boolean.TRUE.equals(expression.getValue(context, Boolean.class));}return false;}
}

定义用户上下文

有的同学会问,你权限校验的逻辑呢?别急,关键点在这:StandardEvaluationContext context = new StandardEvaluationContext(authContext );在上文代码中找到了吧。

这个AuthFun就是我们进行权限校验的对象。所以呢,我们还得在定义一下这个对象。进行具体的权限校验逻辑处理,这里定的每一个方法都可以作为表达式在权限注解中使用。代码如下:
方法对应PreAuth中的方法字符串

@Component
public class AuthContext {private static final ThreadLocal<UserContext> USER_CONTEXT_THREAD_LOCAL = new NamedThreadLocal<>("user context");public static void setUserContext(UserContext user){USER_CONTEXT_THREAD_LOCAL.set(user);}public static UserContext getUserContext(){return USER_CONTEXT_THREAD_LOCAL.get();}public static void removeUserContext(){USER_CONTEXT_THREAD_LOCAL.remove();}/*** 判断角色是否具有接口权限** @param permission 权限编号,对应菜单的MENU_CODE* @return {boolean}*/public boolean hasPermission(String permission) {//TODOreturn hasAnyPermission(permission);}/*** 判断角色是否具有接口权限** @param permission 权限编号,对应菜单的MENU_CODE* @return {boolean}*/public boolean hasAllPermission(String... permission) {//TODOfor (String r : permission) {if (!hasPermission(r)) {return false;}}return true;}/*** 放行所有请求** @return {boolean}*/public boolean permitAll() {return true;}/*** 只有超管角色才可访问** @return {boolean}*/public boolean denyAll() {return hasRole("admin");}/*** 是否有时间授权** @param start 开始时间* @param end   结束时间* @return {boolean}*/public boolean hasTimeAuth(Integer start, Integer end) {/*Integer hour = DateUtil.hour();return hour >= start && hour <= end;*/return true;}/*** 判断是否有该角色权限** @param role 单角色* @return {boolean}*/public boolean hasRole(String role) {return hasAnyRole(role);}/*** 判断是否具有所有角色权限** @param role 角色集合* @return {boolean}*/public boolean hasAllRole(String... role) {for (String r : role) {if (!hasRole(r)) {return false;}}return true;}/*** 判断是否有该角色权限** @param roles 角色集合* @return {boolean}*/public boolean hasAnyRole(String... roles) {UserContext user = getUser();if(user!= null){return hasAnyStr(user.getRoles(),roles);}return false;}/*** 判断是否有该角色权限** @param authorities 角色集合* @return {boolean}*/public boolean hasAnyPermission(String... authorities) {UserContext user = getUser();if(user!= null){return hasAnyStr(user.getAuthorities(),authorities);}return false;}public boolean hasAnyStr(String hasStrings,String... strings) {if(StringUtil.isNotEmpty(hasStrings)){String[] roleArr = hasStrings.split(SymbolConstant.COMMA);return Arrays.stream(strings).anyMatch(r-> Arrays.asList(roleArr).contains(r));}return false;}public UserContext getUser(){UserContext o = AuthContext.getUserContext();if(o != null){return  o;}return null;}}

三、测试

在使用的时候,我们只需要在类上或者接口上,加上@PreAuth的直接,value值写的时候要注意一下,value应该是我们在AuthContext 类中定义的方法和参数,如我们定义了解析方法hasAllRole(String… role),那么在注解中,我们就可以这样写@PreAuth(“hasAllRole(‘角色1’,‘角色2’)”),需要注意的是,参数要用单引号包括。
根据上面的实际使用,可以看到。SpEL表达式解析将我们注解中的"hasAllRole(‘角色1’,‘角色2’)"这样的字符串,给动态解析为了hasAllRole(参数1,参数1),并调用我们注册类中同名的方法。

新建Service在方法上注解

@Slf4j
@Component
public class AuthTestMethodService {@PreAuth("hasRole('admin')")public void testHasRole(){log.info("测试 hasRole('admin')");}@PreAuth("hasAnyRole('admin','test')")public void testHasAnyRole(){log.info("测试 testHasAnyRole('admin')");}@PreAuth("hasAllRole('admin','test')")public void testHasAllRole(){log.info("测试 testHasAllRole('admin')");}@PreAuth("hasPermission('sys:user:add')")public void testHasPermission(){log.info("测试 hasPermission('admin')");}
}

新建Service在类上注解

@Slf4j
@Component
@PreAuth("hasRole('admin')")
public class AuthTestClassService {public void testHasRole(){log.info("测试 hasRole('admin')");}}

运行


@FunctionalInterface
public interface Executer {/*** 执行*/void run();
}
...
...@SpringBootTest
public class AuthTest {@Resourceprivate AuthTestMethodService authTestService;@Resourceprivate AuthTestClassService authTestClassService;@Testvoid testInit(){AuthTestMethodService authTestService2 = new AuthTestMethodService();authTestService2.testHasRole();System.out.println("================");UserContext user = new UserContext();user.setRoles("admin,test");/* testAuth(user,()->{authTestService.testHasRole();});*/testAuth(user,()->{authTestService.testHasRole();authTestService.testHasAllRole();});user.setRoles("test");testAuth(user,()->{authTestService.testHasAnyRole();authTestService.testHasAllRole();});}@Testvoid testClass(){System.out.println("================");UserContext user = new UserContext();user.setRoles("admin,test");testAuth(user,()->{authTestClassService.testHasRole();});user.setRoles("test");testAuth(user,()->{authTestClassService.testHasRole();});}private void testAuth(UserContext user, Executer executer) {AuthContext.setUserContext(user);// 执行try{executer.run();}catch (Exception e){throw e;}finally {AuthContext.removeUserContext();}}}

在这里插入图片描述

http://www.yayakq.cn/news/912170/

相关文章:

  • 湖北省建设厅网站首页展厅建筑设计厂家
  • 渝中集团网站建设网络软件
  • 网站制作好吗阳江企业网站排名优化
  • html5网站建设 教程视频跟业务合作做网站给多少提成
  • 做网站的图片房产福建网站建设优化
  • 做门户网站多少钱手机wap网站定位
  • 贵阳观山湖区网站建设wordpress中文游戏门户
  • 做网站推广有效果吗企业官网建设哪家好
  • 微信官方网站wordpress页面制作视频
  • 义乌 网站建设推广营销网店推广引流
  • 中国建设银行网上银行官方网站公司宣传片制作价格
  • 网站建设技能描述门店装修设计
  • 我要学习网站建设我的世界做皮肤的网站
  • 台州网站优化公司商城网站开发文档
  • asp网站改成php深圳网站设计 制作
  • 玉田网站建设做网站公司赚钱吗
  • 3g下订单的网站怎么做WordPress网易云插卡
  • 网站出现500必须做网站等级保护
  • 基于搜索引擎的网站推广方式中国铁路建设工程招标网站
  • 百度网站官方认证怎么做企业qq注册申请
  • 网站 内容建设存在的问题城市建设法规考试网站
  • 如何创建网站和域名广东东莞公司有哪些
  • 昆明hph网站建设淄博论坛网站建设
  • 网络推广就是做网站吗北京建设工程信息网上报名基础信息
  • 南沙区建设局网站郑州市建设安全监督站网站
  • 广州技术支持:网站建设湖南省建设厅官网网站
  • 苏州网站建设最好joomla 网站模版
  • 网站如何维护oa系统开发公司
  • 网站建设服务费标准如何跟进psd做网站
  • 南昌网站设计资讯购物网站后台模板下载