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

网站信息报送制度建设企业整站优化

网站信息报送制度建设,企业整站优化,wordpress跳转指定模板,招聘做网站Spring Security 6.0 Migration https://docs.spring.io/spring-security/reference/5.8/migration/servlet/config.html 最近在做SpringBoot2.x到3.0的升级。其中最主要的一部分是javax -> jakartapackageName的变更,另外一部分是对一些废弃/删除的类进行替换。…

Spring Security 6.0 Migration

https://docs.spring.io/spring-security/reference/5.8/migration/servlet/config.html
最近在做SpringBoot2.x到3.0的升级。其中最主要的一部分是javax -> jakartapackageName的变更,另外一部分是对一些废弃/删除的类进行替换。大部分升级都比较顺利,但是在SpringSecurity上遇到了不少坑。

先看一下下面的代码

    @Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().csrf().disable().authorizeRequests().expressionHandler(webExpressionHandler());registry.antMatchers("/servlet1/**").permitAll().antMatchers("/servlet2/**").permitAll().antMatchers("/**").access("isLoggedIn()");return http.build();}

这段代码在6.0有两个问题,一是authorizeRequests标记为废弃,二是antMatchers方法被移除,这两个问题我们一个个看。

antMatchers -> requestMatchers

首先看一下antMatchers方法被移除的问题,随便搜一下就可以找到答案,使用requestMatchers来进行替代,看起来非常简单,替换之后我们启动server之后随便访问一下API,结果
在这里插入图片描述
随后又切换了几个发现全都是403,看log里也没有任何Error,怀疑是Spring进行了拦截,随后我们打开Trace级别的log,随后发现了如下信息
2023-03-22 15:44:32,746] [TRACE] 61259 [http-nio-8183-exec-2] edFilterInvocationSecurityMetadataSource - 59C004B425A34C0B96B01682C54B8B2C_1679471072599 - Did not match request to Mvc [pattern='/servlet1/**'] - [permitAll] (11/22)
我们的请求是GET localhost:8080/context/servlet1/test,怎么会不匹配呢?最后通过debug发现,在SpringSecurity6.0中,默认使用的是MvcRequestMatcher
它在匹配的时候会将context-pathservlet-path都去掉之后再进行匹配,拿上面的例子来说是用/test/servlet1/**进行匹配,匹配不上就会返回unauthorized 403。

由于我们项目中是多servlet的形式(历史原因)且API数量非常多,现在要去修改匹配路径非常容易漏掉某些API导致产线问题。然后我们仔细看了requestMatchers的方法内部

	public C requestMatchers(String... patterns) {return requestMatchers(null, patterns);}public C requestMatchers(HttpMethod method, String... patterns) {List<RequestMatcher> matchers = new ArrayList<>();if (mvcPresent) {matchers.addAll(createMvcMatchers(method, patterns));}else {matchers.addAll(RequestMatchers.antMatchers(method, patterns));}return requestMatchers(matchers.toArray(new RequestMatcher[0]));}

mvcPresent这个boolean是根据AbstractRequestMatcherRegistry.class存不存在来设值,这还是一个final变量想要通过修改mvcPresent的值来生成antMatchers似乎不现实,不过很快我们找到了另外一个方法

public C requestMatchers(RequestMatcher... requestMatchers) {Assert.state(!this.anyRequestConfigured, "Can't configure requestMatchers after anyRequest");return chainRequestMatchers(Arrays.asList(requestMatchers));}

这个方法允许我们传入任意一种RequestMatcher,RequestMatchers.antMatchers这个方法也可以为我们产生一个antMatchers,两者结合一下

```java@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().csrf().disable().authorizeRequests().expressionHandler(webExpressionHandler());registry.requestMatchers(antMatchers("/servlet1/**")).permitAll().requestMatchers.(antMatchers("/servlet2/**")).permitAll().requestMatchers("/**").access("isLoggedIn()");return http.build();}

最后测试通过,问题解决!

authorizeRequests() -> authorizeHttpRequests()

authorizeRequests在6.0中被标记为废弃理论上暂时可以不进行处理,但是考虑到以后真正删除之后还要花时间重新再研究一遍,不如一鼓作气都处理掉了。我们先看看spring留下的注释

Deprecated
Use authorizeHttpRequests() instead

看起来非常简单,直接用authorizeHttpRequests()方法进行替代就行了。当我们使用新的方法时遇到了两个error

  • expressionHandler()不存在
  • access()方法不再接受String作为参数
    authorizeRequests()返回的是ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry,而authorizeHttpRequests返回的是AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry,两者不同方法也不能完全替代。
    首先简单介绍一下这两个方法做了什么,expressionHandler()接受一个SecurityExpressionHandler作为参数,这个handler中有一个方法createSecurityExpressionRoot
	@Overrideprotected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication,FilterInvocation fi) {WebSecurityExpressionRoot root = new WebSecurityExpressionRoot(authentication, fi);root.setPermissionEvaluator(getPermissionEvaluator());root.setTrustResolver(this.trustResolver);root.setRoleHierarchy(getRoleHierarchy());root.setDefaultRolePrefix(this.defaultRolePrefix);return root;}

createSecurityExpressionRoot的第一行需要创建一个WebSecurityExpressionRoot,这个root负责解析access(expression)中的expression表达式,在本例中我们自定义的WebSecurityExpressionRoot中有一个isLoggedIn()方法,该方法返回一个boolean用于authorization判断。看到这里大概就可以明白 expressionHandler()access()是配套使用的,一个负责设置expression表达式,一个负责解析表达式,主要的作用是判断request是否被授权。

然后我们看一下AuthorizationManagerRequestMatcherRegistry的access方法

public AuthorizationManagerRequestMatcherRegistry access(AuthorizationManager<RequestAuthorizationContext> manager) {Assert.notNull(manager, "manager cannot be null");return AuthorizeHttpRequestsConfigurer.this.addMapping(this.matchers, manager);}

该方法接收AuthorizationManager作为参数,我们再看一下AuthorizationManager的定义

/*** An Authorization manager which can determine if an {@link Authentication} has access to* a specific object.** @param <T> the type of object that the authorization check is being done one.* @author Evgeniy Cheban*/
@FunctionalInterface
public interface AuthorizationManager<T> {/*** Determines if access should be granted for a specific authentication and object.* @param authentication the {@link Supplier} of the {@link Authentication} to check* @param object the {@link T} object to check* @throws AccessDeniedException if access is not granted*/default void verify(Supplier<Authentication> authentication, T object) {AuthorizationDecision decision = check(authentication, object);if (decision != null && !decision.isGranted()) {throw new AccessDeniedException("Access Denied");}}/*** Determines if access is granted for a specific authentication and object.* @param authentication the {@link Supplier} of the {@link Authentication} to check* @param object the {@link T} object to check* @return an {@link AuthorizationDecision} or null if no decision could be made*/@NullableAuthorizationDecision check(Supplier<Authentication> authentication, T object);}

AuthorizationManager其实很简单,主要就是实现check方法来返回对应的AuthorizationDecision。至此我们似乎已经有了解决方案,我们可以自定一个AuthorizationManager,将isLoggedIn()的逻辑放入其中即可。不过在查看Spring Migration的文档的过程中,我们发现了一个有意思的类WebExpressionAuthorizationManager

	/*** Creates an instance.* @param expressionString the raw expression string to parse*/public WebExpressionAuthorizationManager(String expressionString) {Assert.hasText(expressionString, "expressionString cannot be empty");this.expression = this.expressionHandler.getExpressionParser().parseExpression(expressionString);}/*** Sets the {@link SecurityExpressionHandler} to be used. The default is* {@link DefaultHttpSecurityExpressionHandler}.* @param expressionHandler the {@link SecurityExpressionHandler} to use*/public void setExpressionHandler(SecurityExpressionHandler<RequestAuthorizationContext> expressionHandler) {Assert.notNull(expressionHandler, "expressionHandler cannot be null");this.expressionHandler = expressionHandler;this.expression = expressionHandler.getExpressionParser().parseExpression(this.expression.getExpressionString());}

WebExpressionAuthorizationManager的构造函数需要传入一个expression表达式,并提供了一个方法setExpressionHandler,这一切不正是我们所需要的!
需要注意的是,虽然都是SecurityExpressionHandler,但是泛型参数不同需要我们做些调整
最后,代码如下

@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {var authorizationManager = new WebExpressionAuthorizationManager("isLoggedIn()");authorizationManager.setExpressionHandler(webExpressionHandler());ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().csrf().disable().authorizeHttpRequests();registryregistry.requestMatchers(antMatchers("/servlet1/**")).permitAll().requestMatchers.(antMatchers("/servlet2/**")).permitAll().requestMatchers("/**").access(authorizationManager);return http.build();}
http://www.tj-hxxt.cn/news/100972.html

相关文章:

  • 网站设计像素推广平台排行榜
  • 国外科技类网站百度怎么推广自己的网站
  • 长沙做网站公司2345网址导航是病毒吗
  • 企业网站建立答辩问题b站推广网站2024下载
  • 建网站前期设计用那软件竞价账户托管公司
  • 网站源码上传到空间以后怎么做深圳白帽优化
  • 做网站的变成语言哪类最简单广州搜索seo网站优化
  • 网站建设用什么代码电子商务网站建设的步骤
  • 省 两学一做 专题网站百度地图导航2022最新版
  • 山东日照网站建设谷歌搜索引擎入口google
  • 中国建设部网站全球疫情最新数据统计
  • 深圳做网站联系电话搜索引擎广告形式有
  • 做网站找王思奇百度学术查重
  • 随机图片网站北京疫情最新情况
  • 网站建设与管理自考重点什么叫做优化
  • 做国际生意的网站有哪些最新推广赚钱的app
  • 做淘宝链接网站百度登录入口百度
  • 汕头教育的网站建设百度网络小说排行榜
  • 网站建设教程 epub深圳谷歌推广公司
  • 做网站职校选什么专业百度搜索引擎优化指南最新版
  • 房屋设计图平面图苏州seo关键词优化报价
  • 用html能做企业网站吗网络营销的具体形式种类
  • 军事新闻网关键词优化软件排行
  • 个人网站设计英文网站推广
  • 南昌网站建设公司好么网络营销和电子商务的区别
  • 企业网站建设的注意事项百度秒收录蜘蛛池
  • 如何搭建电影网站网站排名软件利搜
  • 手机网站分辨率做多大百度一下照片识别
  • 汉口网站推广公司链接制作软件
  • 开发区网站建设网络营销首先要做什么