我使用springboot的时候想做自己的配置文件的,用不了xml就重写了过滤器
首先需要了解spring security内置的各种filter:
Alias | Filter Class | Namespace Element or Attribute |
---|---|---|
CHANNEL_FILTER | ChannelProcessingFilter | http/intercept-url@requires-channel |
SECURITY_CONTEXT_FILTER | SecurityContextPersistenceFilter | http |
CONCURRENT_SESSION_FILTER | ConcurrentSessionFilter | session-management/concurrency-control |
HEADERS_FILTER | HeaderWriterFilter | http/headers |
CSRF_FILTER | CsrfFilter | http/csrf |
LOGOUT_FILTER | LogoutFilter | http/logout |
X509_FILTER | X509AuthenticationFilter | http/x509 |
PRE_AUTH_FILTER | AbstractPreAuthenticatedProcessingFilter Subclasses | N/A |
CAS_FILTER | CasAuthenticationFilter | N/A |
FORM_LOGIN_FILTER | UsernamePasswordAuthenticationFilter | http/form-login |
BASIC_AUTH_FILTER | BasicAuthenticationFilter | http/http-basic |
SERVLET_API_SUPPORT_FILTER | SecurityContextHolderAwareRequestFilter | http/@servlet-api-provision |
JAAS_API_SUPPORT_FILTER | JaasApiIntegrationFilter | http/@jaas-api-provision |
REMEMBER_ME_FILTER | RememberMeAuthenticationFilter | http/remember-me |
ANONYMOUS_FILTER | AnonymousAuthenticationFilter | http/anonymous |
SESSION_MANAGEMENT_FILTER | SessionManagementFilter | session-management |
EXCEPTION_TRANSLATION_FILTER | ExceptionTranslationFilter | http |
FILTER_SECURITY_INTERCEPTOR | FilterSecurityInterceptor | http |
SWITCH_USER_FILTER | SwitchUserFilter | N/A |
FilterSecurityInterceptor
这个filter有几个要素,如下:
- SecurityMetadataSource
- AccessDecisionManager
- AuthenticationManager
可以根据情况自己去重新设置,这里我们重写一下SecurityMetadataSource用来动态获取url权限配置,还有AccessDecisionManager来进行权限判断
MyFilterInvocationSecurityMetadataSource这个是用来配置URL的可以从配置文件中拿也可以从数据库中取
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.util.AntPathMatcher;
import com.alibaba.fastjson.JSONObject;
import com.ewe.user.utils.FormatUtils;
public class MyFilterInvocationSecurityMetadataSource implements org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource {
//配置文件的加载
private static String urlRoleMap;
private static final Logger LOGGER = LoggerFactory.getLogger(MyUserDetails.class);
static {
Properties prop = new Properties();
InputStream in = Object.class.getResourceAsStream("/spring-security.properties");
LOGGER.error("加载URL的配置文件");
try {
prop.load(in);
urlRoleMap = prop.getProperty("urls").trim();
} catch (IOException e) {
LOGGER.error("spring-security.properties配置路径不存在{}",e.getMessage());
e.printStackTrace();
}
}
private final AntPathMatcher antPathMatcher = new AntPathMatcher();
@Override
public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
FilterInvocation fi = (FilterInvocation) object;
StringBuffer roles = new StringBuffer("START");
String url = fi.getRequestUrl();
// String httpMethod = fi.getRequest().getMethod();
JSONObject jsonObject=null;
try {
jsonObject = JSONObject.parseObject(urlRoleMap);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String value="";
//遍历json
for(String key: jsonObject.keySet()){
if(antPathMatcher.match(key,url)){
value=jsonObject.getString(key);
//如果有,号的就说明是多个角色
roles.append(","+value);
}
}
if(!("START").equals(roles)){
return SecurityConfig.createList(roles.toString());
}else{
LOGGER.error("没有匹配到URL");
//没有匹配到
// return SecurityConfig.createList("NULL");
throw new AccessDeniedException("not allow");
}
// return null;
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
@Override
public boolean supports(Class<?> clazz) {
return FilterInvocation.class.isAssignableFrom(clazz);
}
}
urls={\
"/users/login":"NONE",\
"/users/register":"NONE",\
"/users/logout**":"ADMIN,CEO,MANAGER,ASSISTANT,EMPLOYEE",\
"/users":"ADMIN,CEO,MANAGER,ASSISTANT,EMPLOYEE",\
"/users/*":"ADMIN,CEO,MANAGER,ASSISTANT,EMPLOYEE",\
"/users/*/password/":"ADMIN,CEO,MANAGER,ASSISTANT,EMPLOYEE",\
"/users/*/freeze":"ADMIN,CEO,MANAGER,ASSISTANT,EMPLOYEE",\
"/users/*/activate":"ADMIN,CEO,MANAGER,ASSISTANT,EMPLOYEE",\
"/users/info**":"ADMIN,CEO,MANAGER,ASSISTANT,EMPLOYEE",\
\
"/roles*":"ADMIN,CEO,MANAGER,ASSISTANT",\
"/roles/*":"ADMIN,CEO,MANAGER,ASSISTANT",\
"/roles/*/add-user":"ADMIN,CEO,MANAGER,ASSISTANT",\
"/roles/*/remove-user":"ADMIN,CEO,MANAGER,ASSISTANT",\
\
"/employees":"ADMIN,CEO,MANAGER,ASSISTANT",\
"/employees/batch":"ADMIN,CEO,MANAGER,ASSISTANT",\
"/employees/*":"ADMIN,CEO,MANAGER,ASSISTANT",\
"/employees*":"ADMIN,CEO,MANAGER,ASSISTANT",\
"/employees/expired-tips*":"ADMIN,CEO,MANAGER,ASSISTANT",\
\
"/passports*":"ADMIN,CEO,MANAGER,ASSISTANT",\
"/passports/*":"ADMIN,CEO,MANAGER,ASSISTANT",\
\
"/payment":"ADMIN,CEO,MANAGER,ASSISTANT",\
"/payment/*":"ADMIN,CEO,MANAGER,ASSISTANT",\
\
"/salary":"ADMIN,CEO,MANAGER,ASSISTANT",\
"/salary*":"ADMIN,CEO,MANAGER,ASSISTANT",\
"/salary/*":"ADMIN,CEO,MANAGER,ASSISTANT",\
\
"/jobs":"ADMIN,CEO,MANAGER,ASSISTANT",\
"/jobs/**":"ADMIN,CEO,MANAGER,ASSISTANT",\
\
"/files":"ADMIN,CEO,MANAGER,ASSISTANT",\
"/files/batch":"ADMIN,CEO,MANAGER,ASSISTANT",\
\
"/dictionary/*":"ADMIN,CEO,MANAGER,ASSISTANT",\
"/dictionary**":"ADMIN,CEO,MANAGER,ASSISTANT"\
}
MyAccessDecisionManager用来验证url的
这里遍历判断该url所需的角色看用户是否具备,有具备则返回,都不具备则抛出AccessDeniedException异常
package
com.ewe.user.security;
import java.util.Collection;
import java.util.Iterator;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.util.CollectionUtils;
public class MyAccessDecisionManager implements org.springframework.security.access.AccessDecisionManager {
@Override
public void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException {
//这段代码其实不需要,因为spring-security-core-4.1.4.RELEASE-sources.jar!/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java第215行判断提前返回了,不会进入decide方法
if (CollectionUtils.isEmpty(configAttributes)) {
throw new AccessDeniedException("not allow");
}
Iterator<ConfigAttribute> ite = configAttributes.iterator();
while (ite.hasNext()) {
ConfigAttribute ca = ite.next();
String needRole = ((org.springframework.security.access.SecurityConfig) ca).getAttribute();
String[] roles =needRole.split(",");
for (GrantedAuthority ga : authentication.getAuthorities()) {
for(String role1:roles){
//登陆注册的通过
if(("NONE").equals(role1)){
//匹配到有对应角色,则允许通过
return;
}
if(ga.getAuthority().equals(role1)){
//匹配到有对应角色,则允许通过
return;
}
}
}
}
//该url有配置权限,但是当然登录用户没有匹配到对应权限,则禁止访问
throw new AccessDeniedException("not allow");
}
@Override
public boolean supports(ConfigAttribute attribute) {
return true;
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
}
最后装配我们的规则过滤器
@EnableWebSecurity
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
public <O extends FilterSecurityInterceptor> O postProcess(
O fsi) {
fsi.setSecurityMetadataSource(mySecurityMetadataSource());
fsi.setAccessDecisionManager(myAccessDecisionManager());
return fsi;
}
});
}
@Bean
public FilterInvocationSecurityMetadataSource mySecurityMetadataSource() {
MyFilterInvocationSecurityMetadataSource securityMetadataSource = new MyFilterInvocationSecurityMetadataSource();
return securityMetadataSource;
}
参考下https://segmentfault.com/a/1190000010672041感谢这位楼主,