spring securiy4如何动态加载URL拦截规则

时间:2021-10-20 18:27:54

springsecuriy4官方案例中的URL拦截规则在容器初始化时加载完成,后面如果URL拦截规则需求有变化,则只有修改配置,重启容器。

通过自定义FilterInvocationSecurityMetadataSource实现类 ProtectedUrlSecurityMetadataSource就可以完成URL拦截规则运行时重新加载。 

FilterSecurityInterceptor有一个小bug,所以ProtectedUrlSecurityMetadataSource必须使用配套的FilterSecurityInterceptor子类ProtectedUrlFilter 来进行URL权限验证。bug描述见 https://github.com/spring-projects/spring-security/pull/4997

ProtectedUrlSecurityMetadataSource核心代码见:

/**
     * @param urlMap 存储URL和权限的对应关系
     */
    public synchronized void loadSecurityMetadataSourceFromUrlMap(Map<String, String> urlMap) {
        LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap  = new LinkedHashMap(urlMap.size());
        for (Map.Entry<String, String> entry : urlMap
                .entrySet()) {
            RequestMatcher requestMatcher = new AntPathRequestMatcher(entry.getKey());
            Set<String> set = StringUtils.commaDelimitedListToSet(entry.getValue());
            Collection<ConfigAttribute> configAttributes = new LinkedHashSet<>(set.size());
            for (String str : set) {
                configAttributes.add(new SecurityConfig(str));
            }
            requestMap.put(requestMatcher, configAttributes);

        }
        FilterInvocationSecurityMetadataSource metadataSource =
                new ExpressionBasedFilterInvocationSecurityMetadataSource(requestMap, new DefaultWebSecurityExpressionHandler());
        this.securityMetadataSource = metadataSource;
    }

具体的配置案例见:SpringSecurityConfig.buildProtectedUrlFilter;

如何从数据库中加载URL配置规则?

1.在自己的controller中注入ProtectedUrlSecurityMetadataSource,

2.从数据库中获得所有URL的拦截规则,然后赋值到Map,

3.调用loadSecurityMetadataSourceFromUrlMap方法,完成拦截规则的重新加载。

@Autowired
ProtectedUrlSecurityMetadataSource metadataSource;

@GetMapping("/access/clear")
public String clear() {
    metadataSource.loadSecurityMetadataSourceFromUrlMap(new HashMap<>());
    return "/home";
}
ProtectedUrlSecurityMetadataSource 拦截规则可以使用web security expressions,保留springsecurity4本身的优势部分,同时提供外部接口,可以运行时重新加载拦截规则,提高了灵活性。

强大的WSE :https://springcloud.cc/spring-security-zhcn.html#el-access-web

源码地址:https://gitee.com/json20080301/spring-boot-spring-security-thymeleaf