前言碎语
首先说下背景,博主公司有大概30多个大小应用将配置信息托管在apollo上,因公司业务复杂环境众多,导致idc的配置多达七八个,因为早期apollo(0.8.x)版本不支持idc,namespace等的管理,故今天升级了下apollo到1.2.。升级后发现有的客户端在通过config service meta接口获取接口信息的时候抛rg.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the URL was not normalized.这个异常,而有的客户端可以正常的拿到接口信息,异常详情如下:
org.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the URL was not normalized. at org.springframework.security.web.firewall.StrictHttpFirewall.getFirewalledRequest(StrictHttpFirewall.java:248) at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:194) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
异常原因定位
apollo1.2.x版本的spring boot版本升级到2.x了,相关的spring security也跟着升级到了5.0.x了,当客户端通过http://localhost:8080//app=xx来请求config service接口时就会被spring security默认的HttpFirewall实例StrictHttpFirewall给拒绝掉,根本原因也就是客户端配置dev_meta时尾巴带了/后缀了,而有的客户端没有加尾巴没加/。
解决方案
1.规范客户端config service url的连接配置,去掉尾巴上的/
这个是正确的做法,但是如果公司的项目众多,而且要求所有客户端都修改一遍然后生产重新部署一遍有点困难可以参考下面的方案
2.使用DefaultHttpFirewall替换默认的StrictHttpFirewall
修改apollo的config service代码,用以兼容/和//的请求。在ApolloMetaServiceConfig中新增DefaultHttpFirewall实例实现,如下:
@EnableAutoConfiguration @Configuration @ComponentScan(basePackageClasses = ApolloMetaServiceConfig.class) public class ApolloMetaServiceConfig { /** * 用于支持url中带// 这种请求 * @return */ @Bean public HttpFirewall allowUrlEncodedSlashHttpFirewall() { return new DefaultHttpFirewall(); } }这样改了后就可以兼容/和//,因为apollo的推拉结合+本地缓存的配置获取策略,可以在生产上面无缝升级apollo的最新版本。
其他小问题:
从0.8.x升级到1.2.x
1.Apollo-Portal的apollo_profile需要加上auth,如:-Dapollo_profile=github,auth,不然不会激活SpringSecurityUserService实现
2.apolloportaldb数据库users表可能缺少email字段,详见:https://github.com/ctripcorp/apollo/blob/master/scripts/sql/