Security——权限配置(数据库相关)
2022/1/7 19:09:57
本文主要是介绍Security——权限配置(数据库相关),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
简单配置
先说一下简单的配置,使用原本就有的功能,数据库查询数据,放到Configuration中即可。
package cn.seaboot.admin.security.manager; import cn.seaboot.admin.security.bean.entity.SecurityChain; import cn.seaboot.admin.security.service.SecurityChainService; import cn.seaboot.common.core.CommonUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; import org.springframework.security.core.session.SessionRegistry; import org.springframework.security.core.session.SessionRegistryImpl; import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl; import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; import javax.annotation.Resource; import javax.sql.DataSource; import java.util.List; /** * Security configuration * * @author Mr.css * @date 2020-05-07 23:38 */ @Configuration public class SecurityConfiguration extends WebSecurityConfigurerAdapter { private Logger logger = LoggerFactory.getLogger(SecurityConfiguration.class); @Resource private SecurityChainService securityChainService; /** * HttpSecurity相关配置 * * @param http HttpSecurity */ @Override protected void configure(HttpSecurity http) throws Exception { //鉴权配置,获取数据库中需要授权的URL ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http.authorizeRequests(); List<SecurityChain> chains = securityChainService.queryList(); if (CommonUtils.isNotEmpty(chains)) { for (SecurityChain chain : chains) { if (!chain.getIsDisable() && !"anon".equals(chain.getExps())) { if (chain.getMethod() == null) { registry.antMatchers(chain.getUrl()).access(chain.getExps()); } else { registry.antMatchers(HttpMethod.resolve(chain.getMethod()), chain.getUrl()).access(chain.getExps()); } logger.info("[security] matcher: {} -> {}", chain.getUrl(), chain.getExps()); } } } //以下省略http其它配置 } /** * 白名单配置,白名单判断优先级更高,白名单目录中包含需要鉴权的资源,需要将资源放到别的包下 * * @param web - */ @Override public void configure(WebSecurity web) { WebSecurity.IgnoredRequestConfigurer ignoredRequestConfigurer = web.ignoring(); List<SecurityChain> chains = securityChainService.queryList(); if (CommonUtils.isNotEmpty(chains)) { for (SecurityChain chain : chains) { if (!chain.getIsDisable() && "anon".equals(chain.getExps())) { ignoredRequestConfigurer.antMatchers(chain.getUrl()); logger.info("[security] ignore: {}", chain.getUrl()); } } } } }
复杂配置
涉及到3个对象的使用。
AccessDecisionManager:投票决策,与权限配置进行比较,判断是不是有操作权限;
FilterInvocationSecurityMetadataSource:元数据查找,相当于DAO,根据URL查找权限配置信息;
ObjectPostProcessor:一个代码切面,帮你将代码植入特定环节的接口。
具体配置如下:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Configuration; import org.springframework.security.access.AccessDecisionManager; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; /** * Security configuration * * @author Mr.css * @date 2020-05-07 23:38 */ @Configuration public class SecurityConfiguration extends WebSecurityConfigurerAdapter { private Logger logger = LoggerFactory.getLogger(SecurityConfiguration.class); /** * HttpSecurity相关配置 * * @param http HttpSecurity */ @Override protected void configure(HttpSecurity http) throws Exception { AuthorityPostProcessor urlPostProcessor = new AuthorityPostProcessor(); urlPostProcessor.setAuthorityAccessDecisionManager(new AccessDecisionManager()); urlPostProcessor.setAuthorityMetadataSource(new FilterInvocationSecurityMetadataSource()); http.authorizeRequests() .antMatchers("/login").permitAll() .withObjectPostProcessor(urlPostProcessor) .anyRequest().authenticated(); //下面省略其它配置 } }
AccessDecisionManager
系统默认实现有下面这么几个,Security是以投票的方式实现的,满足条件加1票,不满足减1票,根据满足条件的数量,确定是否有权限进入系统。
如何切换默认的3种决策方式?咱也不知道,推荐查找AbstractSecurityInterceptor相关的代码,找不到配置的话,可以尝试从spring容器中下手。
* {@link AffirmativeBased} 只需有一个投票赞成即可通过; * {@link ConsensusBased} 需要大多数投票赞成即可通过; * {@link UnanimousBased} 需要所有的投票赞成才能通过。
import cn.seaboot.common.exception.ServiceException; import org.springframework.security.access.AccessDecisionManager; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.vote.AffirmativeBased; import org.springframework.security.access.vote.ConsensusBased; import org.springframework.security.access.vote.UnanimousBased; import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.core.Authentication; import org.springframework.stereotype.Component; import java.util.Collection; /** * 投票决策 * <p> * 默认实现: * - {@link AffirmativeBased} 只需有一个投票赞成即可通过; * - {@link ConsensusBased} 需要大多数投票赞成即可通过; * - {@link UnanimousBased} 需要所有的投票赞成才能通过。 * * @author Mr.css * @date 2022-01-06 19:32 */ @Component public class AuthorityAccessDecisionManager implements AccessDecisionManager { /** * 与角色对比,查看是否满足权限 * * @param authentication 用户凭证 * @param object 当前请求路径 * @param configAttributes 权限集合 * @throws AccessDeniedException - */ @Override public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { System.out.println("通过认证:" + authentication); // throw new AccessDeniedException("access denied!"); } /** * 因为我们的特殊写法,这些函数不应该被调用,直接抛出异常,方便我们跟踪意外调用的场景 * * @param attribute - * @return - */ @Override public boolean supports(ConfigAttribute attribute) { throw new ServiceException("UrlAccessDecisionManager's supports(ConfigAttribute attribute) method can not be used"); } /** * 因为我们的特殊写法,这些函数不应该被调用,直接抛出异常,方便我们跟踪意外调用的场景 * * @param clazz - * @return - */ @Override public boolean supports(Class<?> clazz) { throw new ServiceException("UrlAccessDecisionManager's supports(Class<?> clazz) method can not be used"); } }
FilterInvocationSecurityMetadataSource
import cn.seaboot.common.exception.ServiceException; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.stereotype.Component; import org.springframework.util.AntPathMatcher; import java.util.Collection; /** * 权限数据源管理 * * @author Mr.css * @date 2022-01-06 19:29 */ @Component public class AuthorityMetadataSource implements FilterInvocationSecurityMetadataSource { /** * 路径匹配工具 */ private AntPathMatcher antPathMatcher = new AntPathMatcher(); /** * 根据Url查找匹配的路径列表 * * @param object url * @return 所需的权限集合 * @throws IllegalArgumentException - */ @Override public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException { System.out.println("获取URL所需的权限列表"); String requestUrl = ((FilterInvocation) object).getRequestUrl(); return SecurityConfig.createList("ROLE_LOGIN"); } /** * 因为我们的特殊写法,这些函数不应该被调用,直接抛出异常,方便我们跟踪意外调用的场景 * * @return - */ @Override public Collection<ConfigAttribute> getAllConfigAttributes() { throw new ServiceException("SecurityMetadataSource's getAllConfigAttributes() method can not be used"); } /** * 因为我们的特殊写法,这些函数不应该被调用,直接抛出异常,方便我们跟踪意外调用的场景 * * @param clazz - * @return - */ @Override public boolean supports(Class<?> clazz) { throw new ServiceException("SecurityMetadataSource's supports(Class<?> clazz) method can not be used"); } }
这篇关于Security——权限配置(数据库相关)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-25安卓NDK 是什么?-icode9专业技术文章分享
- 2024-12-25caddy 可以定义日志到 文件吗?-icode9专业技术文章分享
- 2024-12-25wordfence如何设置密码规则?-icode9专业技术文章分享
- 2024-12-25有哪些方法可以实现 DLL 文件路径的管理?-icode9专业技术文章分享
- 2024-12-25错误信息 "At least one element in the source array could not be cast down to the destination array-icode9专业技术文章分享
- 2024-12-25'flutter' 不是内部或外部命令,也不是可运行的程序 或批处理文件。错误信息提示什么意思?-icode9专业技术文章分享
- 2024-12-25flutter项目 as提示Cannot resolve symbol 'embedding'提示什么意思?-icode9专业技术文章分享
- 2024-12-24怎么切换 Git 项目的远程仓库地址?-icode9专业技术文章分享
- 2024-12-24怎么更改 Git 远程仓库的名称?-icode9专业技术文章分享
- 2024-12-24更改 Git 本地分支关联的远程分支是什么命令?-icode9专业技术文章分享