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

自学设计软件的免费网站免费ppt模板简约

自学设计软件的免费网站,免费ppt模板简约,非常酷的wordpress主题,墨刀网页设计详细教程前言 Spring Security有两种配置方式#xff0c;今天重点是绍基于方法配置的方式。 基于方法配置权限 这个主要是有一些注解提供给大家使用#xff0c;今天来给大家一个demo#xff08;参考自官方sample#xff09;。 maven就不多累赘了。重点看看配置。 基于角色配置…前言 Spring Security有两种配置方式今天重点是绍基于方法配置的方式。 基于方法配置权限 这个主要是有一些注解提供给大家使用今天来给大家一个demo参考自官方sample。 maven就不多累赘了。重点看看配置。 基于角色配置 /*** 启用方法安全EnableMethodSecurity* * 启用secured注解: **securedEnabled true*** p会导入配置SecuredMethodSecurityConfigurationp* * 启用PreAuthorizePostAuthorizePreFilterPostFilter**prePostEnabled false*** p会导入配置PrePostMethodSecurityConfiguration/p* * 启用jsr250相关的安全注解**jsr250Enabled true*** p会导入配置Jsr250MethodSecurityConfiguration/p* pjsr250包括RolesAllowedPermitAllDenyAll/p*/ Configuration EnableMethodSecurity(securedEnabled true, prePostEnabled true, jsr250Enabled true) public class AspectjSecurityConfig {}/*** 这个类的所有方法都需要有ROLE_USER角色才能执行*/ Service Secured(ROLE_USER) public class SecuredService {public void secureMethod() {// nothing}}Service public class SecuredService {public void publicMethod() {// nothing}/*** 这个方法需要ROLE_USER才能执行* 这三种配置方式都是等价的只是提供支持的Advice不同。*/ Secured(ROLE_USER)// RolesAllowed(ROLE_USER)// PreAuthorize(hasRole(ROLE_USER))public void secureMethod() {// nothing}PreAuthorize(arguments[0] ne tony)// PreAuthorize(filterObject ne tony)public void preAuthorize(RequestParam(userCode) String userCode) {// preAuthorize不会赋值ROOT的filterObject和returnObject因此无法使用入参。只能使用MethodSecurityExpressionRoot的其他方法// 这个方法的实验现象为不管传什么都能通过表达式logger.info(preAuthorize:{}, userCode);// nothing}/** * 这个入参会被过滤地只剩下与authentication.name一样的*/ PreFilter(filterObject authentication.name)public void preFilter(RequestParam(userCodeList) ListString userCodeList) {// http://localhost:8090/foo/preFilter?userCodeListleo,tonylogger.info(preAuthorize:{}, userCode);}/*** 这个方法需要ROLE_USER才能执行*/ PostAuthorize(returnObject ne tony)public String postAuthorize(RequestParam(userCode) String userCode) {// 传入的是不是tony会抛出异常: 403logger.info(postAuthorize:{}, userCode);return userCode;}GetMapping(/preAuthorizeSpel)PreAuthorize(hasAuthority(permission:read) || hasRole(ADMIN))public void preAuthorizeHasRole() {logger.info(preAuthorizeSpel:{}, userCode);// nothing}/*** 这个方法需要ROLE_USER才能执行*/ PostFilter(returnObject authentication.name)public ListString PostFilter(RequestParam(userCodeList) ListString userCodeList) {// 实验结果就是传入了的参数有值但只有跟用户名一样的才会返回logger.info(PostFilter:{}, userCodeList);return userCodeList;}} 以上就是怎么使用接着我们看下是如何实现的。 基于方法授权方式的实现原理 前面我们说过是基于AOP实现的。那么现在我们从源码层面来看看。 我们可以看到上面按照EnableMethodSecurity的配置分别对应地导入三个配置。 但是我们可以先从AOP的角度设想一下我们需要的是哪种类型的通知不妨归类一下 注解类型通知类型描述/备注PreFilterPreAuthorizeSecured以及JSR-250的相关注解前置通知这些很明显都是需要先校验/过滤参数再执行目标方法PostFilterPostAuthorize后置通知先执行目标方法再校验/过滤结果集 接着我们来看看Spring Security的设计 AuthorizationManagerBeforeMethodInterceptor 在执行方法之前进行鉴权这也意味着当权限不足时他会抛出异常。 实际上他是一个通用的增强全取决于你怎么使用它。 在SpringSecurity的配置里他可以负责PreAuthor也可以负责Secured甚至还能负责jsr250的相关注解。 需要提醒一点一个实例对象只能一种注解哈。 但是大家有没有想过一个问题为什么PreAuthorSecured以及jsr250的相关注解都能交给他来处理 又或者说他的设计是如何将这三者的处理抽象统一起来的更具体一点此三者有何共同之处可以进行抽象和统一的 要回答这个问题我们需要先从这个三者的入手 共同点 都需要在执行方法前进行权限校验校验不通过则都需要抛出异常阻断方法调用。 异同点 注解配置描述执行PreAuthorize配置的是SPEL表达式通过执行表达式来得出是否满足访问权限Secured指定角色需要校验当前用户是否拥有指定角色jsr250的PermitAll-任何人都可以访问jsr250的DenyAll-任何人都不能访问jsr250的RolesAllowed指定角色需要校验当前用户是否拥有指定角色 从共同点出发本质上无非就是鉴权嘛这不是很符合Spring Security的AuthorizationManager的职责吗 然后就是不同点我们发现无非就是权限的配置来源不同需要解析不同的注解咯。 有了这个思路接下来我们翻找源码理解起来就容易多了。 public final class AuthorizationManagerBeforeMethodInterceptorimplements Ordered, MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {// 构造器需要传入Pointcut和AuthorizationManagerMethodInvocation以便校验权限。public AuthorizationManagerBeforeMethodInterceptor(Pointcut pointcut,AuthorizationManagerMethodInvocation authorizationManager) {Assert.notNull(pointcut, pointcut cannot be null);Assert.notNull(authorizationManager, authorizationManager cannot be null);this.pointcut pointcut;this.authorizationManager authorizationManager;}/*** 创建负责处理PreAuthorize的增强*/public static AuthorizationManagerBeforeMethodInterceptor preAuthorize(PreAuthorizeAuthorizationManager authorizationManager) {AuthorizationManagerBeforeMethodInterceptor interceptor new AuthorizationManagerBeforeMethodInterceptor(AuthorizationMethodPointcuts.forAnnotations(PreAuthorize.class), authorizationManager);interceptor.setOrder(AuthorizationInterceptorsOrder.PRE_AUTHORIZE.getOrder());return interceptor;}/*** 创建负责处理Secured*/public static AuthorizationManagerBeforeMethodInterceptor secured(SecuredAuthorizationManager authorizationManager) {AuthorizationManagerBeforeMethodInterceptor interceptor new AuthorizationManagerBeforeMethodInterceptor(AuthorizationMethodPointcuts.forAnnotations(Secured.class), authorizationManager);interceptor.setOrder(AuthorizationInterceptorsOrder.SECURED.getOrder());return interceptor;}/*** 创建负责处理jsr250相关注解: RolesAllowPermitAllDenyAll*/public static AuthorizationManagerBeforeMethodInterceptor jsr250(Jsr250AuthorizationManager authorizationManager) {AuthorizationManagerBeforeMethodInterceptor interceptor new AuthorizationManagerBeforeMethodInterceptor(AuthorizationMethodPointcuts.forAnnotations(RolesAllowed.class, DenyAll.class, PermitAll.class),authorizationManager);interceptor.setOrder(AuthorizationInterceptorsOrder.JSR250.getOrder());return interceptor;}Overridepublic Object invoke(MethodInvocation mi) throws Throwable {// 校验权限attemptAuthorization(mi);return mi.proceed();}private void attemptAuthorization(MethodInvocation mi) {// 通过AuthorizationManager校验权限这意味者AuthorizationManager必须具备解析相关注解的能力实际上他交给了另外一个组件后面会说到。AuthorizationDecision decision this.authorizationManager.check(this.authentication, mi);// 发布授权事件this.eventPublisher.publishAuthorizationEvent(this.authentication, mi, decision);// 不通过就抛出访问拒绝异常if (decision ! null !decision.isGranted()) {throw new AccessDeniedException(Access Denied);}} 从源码我们可以发现之前分析的三类注解只需要一个MethodInterceptor。而他们的不同之处则由AuthorizationManager这个同一个的接口进行统一调度。 对应地 注解AuthorizationManagerPreAuthorizePreAuthorizeAuthorizationManagerSecuredSecuredAuthorizationManagerjsr250的注解Jsr250AuthorizationManager SecuredAuthorizationManager public final class SecuredAuthorizationManager implements AuthorizationManagerMethodInvocation {// 这是个最为简单的AuthorizationManager实现无非就是将当前用户的权限与所需要的权限进行比较如果找到就认为拥有访问权限。private AuthorizationManagerCollectionString authoritiesAuthorizationManager new AuthoritiesAuthorizationManager();// 缓存已经解析过的方法所对应的权限private final MapMethodClassKey, SetString cachedAuthorities new ConcurrentHashMap();Overridepublic AuthorizationDecision check(SupplierAuthentication authentication, MethodInvocation mi) {// 获取目标方法配置的访问权限SetString authorities getAuthorities(mi);// 比较权限从authoritiesAuthorizationManager.check方法的入参也能大概猜到怎么实现return authorities.isEmpty() ? null : this.authoritiesAuthorizationManager.check(authentication, authorities);}private SetString getAuthorities(MethodInvocation methodInvocation) {Method method methodInvocation.getMethod();Object target methodInvocation.getThis();Class? targetClass (target ! null) ? target.getClass() : null;MethodClassKey cacheKey new MethodClassKey(method, targetClass);// 如果尚未存在相关缓存则进行解析。// 由此可见只有当目标方法被第一次执行/调用的时候才会出发解析动作return this.cachedAuthorities.computeIfAbsent(cacheKey, (k) - resolveAuthorities(method, targetClass));}private SetString resolveAuthorities(Method method, Class? targetClass) {Method specificMethod AopUtils.getMostSpecificMethod(method, targetClass);// 尝试在方法上寻找目标注解SecuredSecured secured findSecuredAnnotation(specificMethod);// 返回Secured注解所配置的权限return (secured ! null) ? Set.of(secured.value()) : Collections.emptySet();} }Jsr250AuthorizationManager 相较于SecuredAuthorizationManager他负责的则是3个注解而不是一个。 public final class Jsr250AuthorizationManager implements AuthorizationManagerMethodInvocation {// 这是AuthorizationManager的注册器// 因为要处理三个注解每个注解的处理逻辑虽然简单但是确实不一样。// 而每个方法存在的注解也不一样private final Jsr250AuthorizationManagerRegistry registry new Jsr250AuthorizationManagerRegistry();Overridepublic AuthorizationDecision check(SupplierAuthentication authentication, MethodInvocation methodInvocation) {// 根据方法从注册器中获取对应的AuthorizationManagerAuthorizationManagerMethodInvocation delegate this.registry.getManager(methodInvocation);// 执行授权校验逻辑return delegate.check(authentication, methodInvocation);}// 这是Jsr250AuthorizationManager的内部类private final class Jsr250AuthorizationManagerRegistry extends AbstractAuthorizationManagerRegistry {NonNullOverrideAuthorizationManagerMethodInvocation resolveManager(Method method, Class? targetClass) {// 解析注解Annotation annotation findJsr250Annotation(method, targetClass);if (annotation instanceof DenyAll) {// 返回一个lambda表达式构建的AuthorizationManager其实现为直接返回拒绝访问return (a, o) - new AuthorizationDecision(false);}if (annotation instanceof PermitAll) {// 返回一个lambda表达式构建的AuthorizationManager其实现为直接返回允许访问return (a, o) - new AuthorizationDecision(true);}if (annotation instanceof RolesAllowed) {RolesAllowed rolesAllowed (RolesAllowed) annotation;// 返回与Secured一样的AuthorityAuthorizationManagerreturn AuthorityAuthorizationManager.hasAnyRole(Jsr250AuthorizationManager.this.rolePrefix,rolesAllowed.value());}// 这里应当看到这三个注解的判断顺序。事实上在解析注解的时候只会返回其中之一。// 而jsr250的注解也是不能同时使用的只能用其中一个。return NULL_MANAGER;}} }abstract class AbstractAuthorizationManagerRegistry {private final MapMethodClassKey, AuthorizationManagerMethodInvocation cachedManagers new ConcurrentHashMap();final AuthorizationManagerMethodInvocation getManager(MethodInvocation methodInvocation) {Method method methodInvocation.getMethod();Object target methodInvocation.getThis();Class? targetClass (target ! null) ? target.getClass() : null;MethodClassKey cacheKey new MethodClassKey(method, targetClass);// 这里就跟Secured类似了只不过其需要兼顾3个注解因此value变成了AuthorizationManagerreturn this.cachedManagers.computeIfAbsent(cacheKey, (k) - resolveManager(method, targetClass));} abstract AuthorizationManagerMethodInvocation resolveManager(Method method, Class? targetClass); } PreAuthorizeAuthorizationManager 与他的同伴不同他可是要支持SPEL的。 public final class PreAuthorizeAuthorizationManager implements AuthorizationManagerMethodInvocation {private PreAuthorizeExpressionAttributeRegistry registry new PreAuthorizeExpressionAttributeRegistry();Overridepublic AuthorizationDecision check(SupplierAuthentication authentication, MethodInvocation mi) {// 通过方法从注册器获取ExpressionAttribute。ExpressionAttribute attribute this.registry.getAttribute(mi);if (attribute ExpressionAttribute.NULL_ATTRIBUTE) {return null;}// 通过注册器找到ExpressionHandler并创建EvaluationContextEvaluationContext ctx this.registry.getExpressionHandler().createEvaluationContext(authentication, mi);// 执行SPEL表达式boolean granted ExpressionUtils.evaluateAsBoolean(attribute.getExpression(), ctx);// 返回决策是否允许访问return new ExpressionAuthorizationDecision(granted, attribute.getExpression());} }这里我们看到了为了支持SPEL的第一个抽象ExpressionAttribute。他最重要的使命就是记录表达式。 再来看看最为重要的PreAuthorizeExpressionAttributeRegistry final class PreAuthorizeExpressionAttributeRegistry extends AbstractExpressionAttributeRegistryExpressionAttribute {private final MethodSecurityExpressionHandler expressionHandler;OverrideExpressionAttribute resolveAttribute(Method method, Class? targetClass) {Method specificMethod AopUtils.getMostSpecificMethod(method, targetClass);// 寻找PreAuthorize注解PreAuthorize preAuthorize findPreAuthorizeAnnotation(specificMethod);if (preAuthorize null) {return ExpressionAttribute.NULL_ATTRIBUTE;}// 解析表达式Expression preAuthorizeExpression this.expressionHandler.getExpressionParser().parseExpression(preAuthorize.value());// 返回解析到的表达式return new ExpressionAttribute(preAuthorizeExpression);} }abstract class AbstractExpressionAttributeRegistryT extends ExpressionAttribute {// 缓存方法对应的表达式private final MapMethodClassKey, T cachedAttributes new ConcurrentHashMap();final T getAttribute(Method method, Class? targetClass) {MethodClassKey cacheKey new MethodClassKey(method, targetClass);// 解析并缓存表达式return this.cachedAttributes.computeIfAbsent(cacheKey, (k) - resolveAttribute(method, targetClass));} }AuthorizationManagerAfterMethodInterceptor 他与前面介绍的MethodInterceptor相呼应一前一后你从名字就能发现。只不过与前者相比目前他只有一个注解需要关注PostAuthorize。 public final class AuthorizationManagerAfterMethodInterceptorimplements Ordered, MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {private final AuthorizationManagerMethodInvocationResult authorizationManager;Overridepublic Object invoke(MethodInvocation mi) throws Throwable {// 先执行Object result mi.proceed();// 再校验。这里应当注意到他的入参包括方法返回值attemptAuthorization(mi, result);return result;}private void attemptAuthorization(MethodInvocation mi, Object result) {// 熟悉的配方只不过入参变成了方法返回值罢了MethodInvocationResult object new MethodInvocationResult(mi, result);AuthorizationDecision decision this.authorizationManager.check(this.authentication, object);this.eventPublisher.publishAuthorizationEvent(this.authentication, object, decision);if (decision ! null !decision.isGranted()) {throw new AccessDeniedException(Access Denied);}} }public final class PostAuthorizeAuthorizationManager implements AuthorizationManagerMethodInvocationResult {private PostAuthorizeExpressionAttributeRegistry registry new PostAuthorizeExpressionAttributeRegistry();Overridepublic AuthorizationDecision check(SupplierAuthentication authentication, MethodInvocationResult mi) {ExpressionAttribute attribute this.registry.getAttribute(mi.getMethodInvocation());if (attribute ExpressionAttribute.NULL_ATTRIBUTE) {return null;}MethodSecurityExpressionHandler expressionHandler this.registry.getExpressionHandler();EvaluationContext ctx expressionHandler.createEvaluationContext(authentication, mi.getMethodInvocation());expressionHandler.setReturnObject(mi.getResult(), ctx);boolean granted ExpressionUtils.evaluateAsBoolean(attribute.getExpression(), ctx);return new ExpressionAuthorizationDecision(granted, attribute.getExpression());} }经过了前面的分析这里也就没啥多说的了。与PreAuthorize很相似。 PreFilterAuthorizationMethodInterceptor 负责处理PreFilter注解的方法调用。 public final class PreFilterAuthorizationMethodInterceptorimplements Ordered, MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {public PreFilterAuthorizationMethodInterceptor() {// 默认处理的是PreFilterthis.pointcut AuthorizationMethodPointcuts.forAnnotations(PreFilter.class);}// ...Overridepublic Object invoke(MethodInvocation mi) throws Throwable {// 从属性注册器中获取到目标方法解析好的PreFilter的相关属性信息。PreFilterExpressionAttributeRegistry.PreFilterExpressionAttribute attribute this.registry.getAttribute(mi);if (attribute PreFilterExpressionAttributeRegistry.PreFilterExpressionAttribute.NULL_ATTRIBUTE) {return mi.proceed();}// 从属性注册器中获取对应的SPEL的表达式处理器以便创建SPEL的上下文MethodSecurityExpressionHandler expressionHandler this.registry.getExpressionHandler();EvaluationContext ctx expressionHandler.createEvaluationContext(this.authentication, mi);// 从表达式上下文中获取需要过滤的目标Object filterTarget findFilterTarget(attribute.getFilterTarget(), ctx, mi);// 根据SPEL表达式执行过滤expressionHandler.filter(filterTarget, attribute.getExpression(), ctx);// 执行目标方法return mi.proceed();}// ... }可以看出与PreAuthorize类似只是少了一层AuthorizationManager的封装。原因也很简单AuthorizationManager是用来鉴权的而PreFilter不需要鉴权。 只需要过滤参数即可。因此他也不会抛出访问异常。 PostFilterAuthorizationMethodInterceptor 负责处理PostFilter。 public final class PostFilterAuthorizationMethodInterceptorimplements Ordered, MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {// 这个注册器与PreAuthorizeExpressionAttributeRegistry类似都继承同一个父类。// 只有解析的注解不一样对应ExpressionAttribute稍稍不一样前者记录有方法参数而后者记录有方法返回值。private PostFilterExpressionAttributeRegistry registry new PostFilterExpressionAttributeRegistry();public PostFilterAuthorizationMethodInterceptor() {this.pointcut AuthorizationMethodPointcuts.forAnnotations(PostFilter.class);}Overridepublic Object invoke(MethodInvocation mi) throws Throwable {// 先执行了方法获得返回值Object returnedObject mi.proceed();ExpressionAttribute attribute this.registry.getAttribute(mi);if (attribute ExpressionAttribute.NULL_ATTRIBUTE) {return returnedObject;}// 获取ExpressionHandler创建EvaluationContextMethodSecurityExpressionHandler expressionHandler this.registry.getExpressionHandler();EvaluationContext ctx expressionHandler.createEvaluationContext(this.authentication, mi);// 执行过滤逻辑return expressionHandler.filter(returnedObject, attribute.getExpression(), ctx);}我们可以看到PostFilter只是对返回进行过滤同样也不会抛出访问异常。 小结 分析完源码之后我们不难发现每一个类都很小且每一个方法都足够简单。这点是值得大家学习的。 当然不能盲目。因为作为一款优秀的框架必须要具备良好的可扩展性。通过分析和抽象能够很好起到这个作用。这是框架源码设计者所追求的。 但是其弊端也很明显那就是一个完整的功能实现往往需要诸多组件协作完成初学者很难入门。因此在实际业务开发过程中不能盲目地追求这种扩展性。 同时面对复杂业务时不妨多分析是否可以像框架源码的设计者那样思考当然设计完成后需要留下相当的文档。 总结 各方法注解的应用场景 注解应用场景实现原理Secured配置需要满足的权限可以是角色名或者权限基于AuthorityAuthorizationManagerJSR-250的PermitAll任何人都可以访问基于lambda表达式实现的简单的AuthorizationManagerJSR-250的DenyAll任何人都不能访问基于lambda表达式实现的简单的AuthorizationManagerJSR-250的RolesAllowed配置需要满足的权限可以是角色名或者权限。可以于Secured相互取代。基于AuthorityAuthorizationManager可以于Secured相互取代。PreAuthorize用于在方法调用之前鉴权支持方法入参作为表达式的一部分基于SPEL表达式PostAuthorize用于在方法调用之后鉴权支持方法返回值作为表达式的一部分基于SPEL表达式PreFilter用于过滤方法入参基于SPEL表达式PostFilter用于过滤方法返回值基于SPEL表达式 在搞清楚了各注解的用处和使用后我们在回过头来看我们可以使用哪些授权方式 RBAC(基于角色的访问控制) 这个除了PreFilterPostFilter其他注解都能实现。SPEL可以使用hasAnyRole(ADMIN,USER) 后记 至此我们应该算全方面聊完了基于方法注解怎么配置权限这个话题。不管各个注解的使用场景亦或者其实现原理还是各种设计思路。 下一节我们将聊聊基于HttpRequest的权限配置方式。这个直接使用倒是简单但是想要定制就必须深入理解其设计和原理。加油。 参照 Method Security Spring Security的PreAythorize、PostAuthorize、PreFilter 和PostFilter
http://www.zqtcl.cn/news/185118/

相关文章:

  • 网站建设好学么模版型网站是怎样的
  • 网站维护建设费应计入科目高端营销型网站制作
  • 推荐几个好的网站wordpress 加载数据库表格也卖弄
  • 承德网站开发找人做网站安全吗
  • 百度网站推广电话眼镜网站怎么做竞价
  • 邢台建设银行官方网站为什么建设网站很多公司没有
  • 闵行做网站费用湖南正规网络营销哪家便宜
  • 找个公司做网站需要注意什么wordpress用户名长度
  • 推荐几个没封的正能量网站营销技巧和营销方法视频
  • html mip 网站桂林市临桂区
  • 做网站如何月入10万建行app怎么注册登录
  • 建设一个旅游网站毕业设计建设网站的功能定位是什么原因
  • wordpress网站导航模板杭州建设网站的公司
  • 如何做视频解析网站wordpress 关闭评论
  • 安福网站建设微信开发者工具怎么下载
  • 网罗设计网站威海网页设计制作公司
  • 网站用cmswordpress插件怎么做
  • 如何办好公司网站元器件网站搭建
  • 建设领域行政处罚查询网站wordpress数据库发文章
  • 怎么做网页的多开器宿迁seo优化
  • 别人帮做的网站怎么修改病句店铺引流的30种方法
  • 网站备案幕布怎么申请绍兴cms建站模板
  • 做网站熊掌号软件设计公司排名
  • 深圳 做网站学做西点的网站
  • 静态网站安全性百度服务平台
  • 网站vi设计公司网站建设app
  • 书店网站建设策划书总结每天看七个广告赚40元的app
  • 做网站的属于什么专业成都广告制作安装公司
  • 天津市网站建设公司网站制作费用
  • 网站制作公司 郑州wordpress图片中文不显示解决