mirror of
https://gitee.com/lab1024/smart-admin.git
synced 2025-10-08 21:26:40 +08:00
support
This commit is contained in:
parent
4d0a7943a4
commit
12012eaa70
@ -1,7 +1,6 @@
|
|||||||
package net.lab1024.smartadmin.service.common.security;
|
package net.lab1024.smartadmin.service.common.security;
|
||||||
|
|
||||||
import net.lab1024.smartadmin.service.common.anno.NoValidPrivilege;
|
import net.lab1024.smartadmin.service.common.anno.NoValidPrivilege;
|
||||||
import net.lab1024.smartadmin.service.util.SmartSecurityUtil;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.security.access.ConfigAttribute;
|
import org.springframework.security.access.ConfigAttribute;
|
||||||
import org.springframework.security.access.prepost.*;
|
import org.springframework.security.access.prepost.*;
|
||||||
@ -35,13 +34,13 @@ public class SmartSecurityMetadataSource extends PrePostAnnotationSecurityMetada
|
|||||||
|
|
||||||
private String projectModule;
|
private String projectModule;
|
||||||
|
|
||||||
private List<String> ignoreUrlList;
|
private List<String> noValidUrlList;
|
||||||
|
|
||||||
public SmartSecurityMetadataSource(PrePostInvocationAttributeFactory attributeFactory, List<String> ignoreUrlList, String projectModule) {
|
public SmartSecurityMetadataSource(PrePostInvocationAttributeFactory attributeFactory, List<String> noValidUrlList, String projectModule) {
|
||||||
super(attributeFactory);
|
super(attributeFactory);
|
||||||
this.attributeFactory = attributeFactory;
|
this.attributeFactory = attributeFactory;
|
||||||
this.projectModule = projectModule;
|
this.projectModule = projectModule;
|
||||||
this.ignoreUrlList = ignoreUrlList;
|
this.noValidUrlList = noValidUrlList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -77,10 +76,10 @@ public class SmartSecurityMetadataSource extends PrePostAnnotationSecurityMetada
|
|||||||
return super.getAttributes(method, targetClass);
|
return super.getAttributes(method, targetClass);
|
||||||
}
|
}
|
||||||
//获取注解值
|
//获取注解值
|
||||||
String uriPrefix = SmartSecurityUtil.getUriPrefix(method);
|
String uriPrefix = SmartSecurityUrl.getUriPrefix(method);
|
||||||
List<String> annotationValueList = SmartSecurityUtil.getAnnotationValueList(method, uriPrefix);
|
List<String> annotationValueList = SmartSecurityUrl.getAnnotationValueList(method, uriPrefix);
|
||||||
//判断是否被忽略
|
//判断是否被忽略
|
||||||
if (this.contain(ignoreUrlList, annotationValueList)) {
|
if (this.contain(noValidUrlList, annotationValueList)) {
|
||||||
return super.getAttributes(method, targetClass);
|
return super.getAttributes(method, targetClass);
|
||||||
}
|
}
|
||||||
ArrayList<ConfigAttribute> configAttributes = new ArrayList(1);
|
ArrayList<ConfigAttribute> configAttributes = new ArrayList(1);
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
package net.lab1024.smartadmin.service.common.security;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import net.lab1024.smartadmin.service.common.anno.NoNeedLogin;
|
|
||||||
import net.lab1024.smartadmin.service.util.SmartSecurityUtil;
|
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
|
||||||
import org.reflections.Reflections;
|
|
||||||
import org.reflections.scanners.MethodAnnotationsScanner;
|
|
||||||
import org.reflections.scanners.TypeAnnotationsScanner;
|
|
||||||
import org.reflections.util.ConfigurationBuilder;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [ ]
|
|
||||||
*
|
|
||||||
* @author 罗伊
|
|
||||||
* @date 2021/8/31 10:20
|
|
||||||
*/
|
|
||||||
public class SmartSecurityNoLoginUrl {
|
|
||||||
|
|
||||||
private List<String> noLoginUrlList;
|
|
||||||
|
|
||||||
public SmartSecurityNoLoginUrl(String scanPath){
|
|
||||||
this.noLoginUrlList = this.initNoLoginUrlList(scanPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public List<String> getNoLoginUrlList(){
|
|
||||||
return noLoginUrlList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取无需登录的url信息
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private List<String> initNoLoginUrlList(String scanPath) {
|
|
||||||
List<String> noLoginUrlList = Lists.newArrayList();
|
|
||||||
//一些常量uri
|
|
||||||
noLoginUrlList.add("/swagger-ui.html");
|
|
||||||
noLoginUrlList.add("/swagger-resources/**");
|
|
||||||
noLoginUrlList.add("/webjars/**");
|
|
||||||
noLoginUrlList.add("/*/api-docs");
|
|
||||||
//添加无需登录注解的uri
|
|
||||||
Reflections reflections = new Reflections(new ConfigurationBuilder().forPackages(scanPath).addScanners(new MethodAnnotationsScanner(), new TypeAnnotationsScanner()));
|
|
||||||
Set<Method> methodSet = reflections.getMethodsAnnotatedWith(NoNeedLogin.class);
|
|
||||||
Set<Class<?>> classSet = reflections.getTypesAnnotatedWith(NoNeedLogin.class);
|
|
||||||
//方法级别无需登录
|
|
||||||
for (Method method : methodSet) {
|
|
||||||
String uriPrefix = SmartSecurityUtil.getUriPrefix(method);
|
|
||||||
List<String> valueList = SmartSecurityUtil.getAnnotationValueList(method, uriPrefix);
|
|
||||||
noLoginUrlList.addAll(valueList);
|
|
||||||
}
|
|
||||||
//类级别无需登录
|
|
||||||
for (Class clazz : classSet) {
|
|
||||||
Method[] methods = clazz.getMethods();
|
|
||||||
for (Method method : methods) {
|
|
||||||
String uriPrefix = SmartSecurityUtil.getUriPrefix(method);
|
|
||||||
List<String> valueList = SmartSecurityUtil.getAnnotationValueList(method, uriPrefix);
|
|
||||||
noLoginUrlList.addAll(valueList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return noLoginUrlList;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
package net.lab1024.smartadmin.service.util;
|
package net.lab1024.smartadmin.service.common.security;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -14,7 +14,7 @@ import java.util.List;
|
|||||||
* @author 罗伊
|
* @author 罗伊
|
||||||
* @date 2021/8/31 11:30
|
* @date 2021/8/31 11:30
|
||||||
*/
|
*/
|
||||||
public class SmartSecurityUtil {
|
public class SmartSecurityUrl {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取指定方法的uri 前缀
|
* 获取指定方法的uri 前缀
|
@ -0,0 +1,130 @@
|
|||||||
|
package net.lab1024.smartadmin.service.common.security;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import net.lab1024.smartadmin.service.common.anno.NoNeedLogin;
|
||||||
|
import org.reflections.Reflections;
|
||||||
|
import org.reflections.scanners.MethodAnnotationsScanner;
|
||||||
|
import org.reflections.scanners.TypeAnnotationsScanner;
|
||||||
|
import org.reflections.util.ConfigurationBuilder;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [ ]
|
||||||
|
*
|
||||||
|
* @author 罗伊
|
||||||
|
* @date 2021/8/31 10:20
|
||||||
|
*/
|
||||||
|
public class SmartSecurityUrlMatchers {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 匿名访问URL
|
||||||
|
*/
|
||||||
|
private List<String> PERMIT_URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 忽略的URL(注意,加入忽略的URL,无法进入Security filter)
|
||||||
|
*/
|
||||||
|
private static List<String> IGNORE_URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 需要登录的
|
||||||
|
*/
|
||||||
|
private static List<String> AUTHENTICATED_URL;
|
||||||
|
|
||||||
|
static {
|
||||||
|
IGNORE_URL = new ArrayList<>();
|
||||||
|
IGNORE_URL.add("/swagger-ui.html");
|
||||||
|
IGNORE_URL.add("/swagger-resources/**");
|
||||||
|
IGNORE_URL.add("/webjars/**");
|
||||||
|
IGNORE_URL.add("/*/api-docs");
|
||||||
|
|
||||||
|
AUTHENTICATED_URL = new ArrayList<>();
|
||||||
|
AUTHENTICATED_URL.add("/admin/**");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造函数
|
||||||
|
* @param scanPath 需要扫描的类路径
|
||||||
|
*/
|
||||||
|
public SmartSecurityUrlMatchers(String scanPath){
|
||||||
|
this.PERMIT_URL = this.initAnonymousUrlList(scanPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取忽略的URL集合
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<String> getIgnoreUrlList() {
|
||||||
|
return IGNORE_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getPermitUrlList() {
|
||||||
|
return PERMIT_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getAuthenticatedUrlList() {
|
||||||
|
return AUTHENTICATED_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不需要权限校验的
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<String> getNoValidUrlList() {
|
||||||
|
List<String> noValidUrl = Lists.newArrayList();
|
||||||
|
noValidUrl.addAll(IGNORE_URL);
|
||||||
|
noValidUrl.addAll(PERMIT_URL);
|
||||||
|
return noValidUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String [] getIgnoreUrlArray() {
|
||||||
|
String [] ignoreUrlArray = IGNORE_URL.toArray(new String[IGNORE_URL.size()]);
|
||||||
|
return ignoreUrlArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String [] getPermitUrlArray() {
|
||||||
|
String [] anonymousUrlArray = PERMIT_URL.toArray(new String[PERMIT_URL.size()]);
|
||||||
|
return anonymousUrlArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String [] getAuthenticatedUrlArray() {
|
||||||
|
String [] anonymousUrlArray = AUTHENTICATED_URL.toArray(new String[AUTHENTICATED_URL.size()]);
|
||||||
|
return anonymousUrlArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取无需登录可以匿名访问的url信息
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private List<String> initAnonymousUrlList(String scanPath) {
|
||||||
|
List<String> anonymousUrlList = Lists.newArrayList();
|
||||||
|
//添加无需登录注解的uri
|
||||||
|
Reflections reflections = new Reflections(new ConfigurationBuilder().forPackages(scanPath).addScanners(new MethodAnnotationsScanner(), new TypeAnnotationsScanner()));
|
||||||
|
Set<Method> methodSet = reflections.getMethodsAnnotatedWith(NoNeedLogin.class);
|
||||||
|
Set<Class<?>> classSet = reflections.getTypesAnnotatedWith(NoNeedLogin.class);
|
||||||
|
//方法级别无需登录
|
||||||
|
for (Method method : methodSet) {
|
||||||
|
String uriPrefix = SmartSecurityUrl.getUriPrefix(method);
|
||||||
|
List<String> valueList = SmartSecurityUrl.getAnnotationValueList(method, uriPrefix);
|
||||||
|
anonymousUrlList.addAll(valueList);
|
||||||
|
}
|
||||||
|
//类级别无需登录
|
||||||
|
for (Class clazz : classSet) {
|
||||||
|
Method[] methods = clazz.getMethods();
|
||||||
|
for (Method method : methods) {
|
||||||
|
String uriPrefix = SmartSecurityUrl.getUriPrefix(method);
|
||||||
|
List<String> valueList = SmartSecurityUrl.getAnnotationValueList(method, uriPrefix);
|
||||||
|
anonymousUrlList.addAll(valueList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return anonymousUrlList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,14 +1,17 @@
|
|||||||
package net.lab1024.smartadmin.service.config;
|
package net.lab1024.smartadmin.service.config;
|
||||||
|
|
||||||
import net.lab1024.smartadmin.service.common.security.SmartSecurityNoLoginUrl;
|
import net.lab1024.smartadmin.service.filter.SmartSecurityTokenFilter;
|
||||||
import net.lab1024.smartadmin.service.filters.SmartTokenFilter;
|
import net.lab1024.smartadmin.service.common.security.SmartSecurityUrlMatchers;
|
||||||
import net.lab1024.smartadmin.service.handler.AuthenticationFailHandler;
|
import net.lab1024.smartadmin.service.handler.AuthenticationFailHandler;
|
||||||
|
import net.lab1024.smartadmin.service.module.system.login.EmployeeLoginTokenService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
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.builders.WebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
|
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
import org.springframework.web.cors.CorsConfiguration;
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
@ -20,7 +23,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* Spring Security
|
* Spring Security
|
||||||
*
|
*
|
||||||
* @author 善逸
|
* @author 罗伊
|
||||||
* @date 2021/8/3 17:50
|
* @date 2021/8/3 17:50
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@ -28,30 +31,28 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
|
|
||||||
@Value("${access-control-allow-origin}")
|
@Value("${access-control-allow-origin}")
|
||||||
private String accessControlAllowOrigin;
|
private String accessControlAllowOrigin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 认证失败处理类
|
* 认证失败处理类
|
||||||
*/
|
*/
|
||||||
@Autowired
|
@Autowired
|
||||||
private AuthenticationFailHandler authenticationFailHandler;
|
private AuthenticationFailHandler authenticationFailHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 无需登录的url
|
* url
|
||||||
*/
|
*/
|
||||||
@Autowired
|
@Autowired
|
||||||
private SmartSecurityNoLoginUrl smartSecurityNoLoginUrl;
|
private SmartSecurityUrlMatchers smartSecurityUrlMatchers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* token过滤器
|
* 获取TOKEN 解析类
|
||||||
*/
|
*/
|
||||||
@Autowired
|
@Autowired
|
||||||
private SmartTokenFilter smartTokenFilter;
|
private EmployeeLoginTokenService loginTokenService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 跨域配置
|
* 跨域配置
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@Bean
|
||||||
public CorsFilter corsFilter() {
|
public CorsFilter corsFilter() {
|
||||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||||
CorsConfiguration config = new CorsConfiguration();
|
CorsConfiguration config = new CorsConfiguration();
|
||||||
@ -67,44 +68,34 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
return new CorsFilter(source);
|
return new CorsFilter(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* anyRequest | 匹配所有请求路径
|
|
||||||
* access | SpringEl表达式结果为true时可以访问
|
|
||||||
* anonymous | 匿名可以访问
|
|
||||||
* denyAll | 用户不能访问
|
|
||||||
* fullyAuthenticated | 用户完全认证可以访问(非remember-me下自动登录)
|
|
||||||
* hasAnyAuthority | 如果有参数,参数表示权限,则其中任何一个权限可以访问
|
|
||||||
* hasAnyRole | 如果有参数,参数表示角色,则其中任何一个角色可以访问
|
|
||||||
* hasAuthority | 如果有参数,参数表示权限,则其权限可以访问
|
|
||||||
* hasIpAddress | 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
|
|
||||||
* hasRole | 如果有参数,参数表示角色,则其角色可以访问
|
|
||||||
* permitAll | 用户可以任意访问
|
|
||||||
* rememberMe | 允许通过remember-me登录的用户访问
|
|
||||||
* authenticated | 用户登录后可访问
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity httpSecurity) throws Exception {
|
protected void configure(HttpSecurity httpSecurity) throws Exception {
|
||||||
httpSecurity
|
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry interceptUrlRegistry = httpSecurity
|
||||||
// CSRF禁用,因为不使用session
|
// CSRF禁用,因为不使用session
|
||||||
.csrf().disable()
|
.csrf().disable()
|
||||||
// 认证失败处理类
|
// 认证失败处理类
|
||||||
.exceptionHandling().authenticationEntryPoint(authenticationFailHandler).and()
|
.exceptionHandling().authenticationEntryPoint(authenticationFailHandler).and()
|
||||||
// 基于token,所以不需要session
|
|
||||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
|
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
|
||||||
// 过滤请求
|
// 过滤请求
|
||||||
.authorizeRequests()
|
.authorizeRequests();
|
||||||
.antMatchers("/admin/**").authenticated();
|
//可以匿名登录的URL
|
||||||
|
String [] anonymousUrlArray = smartSecurityUrlMatchers.getPermitUrlArray();
|
||||||
|
interceptUrlRegistry.antMatchers(anonymousUrlArray).permitAll();
|
||||||
|
|
||||||
httpSecurity.addFilterBefore(smartTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
//登录的URL
|
||||||
httpSecurity.addFilterBefore(corsFilter(), SmartTokenFilter.class);
|
String [] authenticatedUrlArray = smartSecurityUrlMatchers.getAuthenticatedUrlArray();
|
||||||
|
interceptUrlRegistry.antMatchers(authenticatedUrlArray).authenticated();
|
||||||
|
|
||||||
|
httpSecurity.addFilterBefore(new SmartSecurityTokenFilter(loginTokenService), UsernamePasswordAuthenticationFilter.class);
|
||||||
|
httpSecurity.addFilterBefore(corsFilter(), SmartSecurityTokenFilter.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configure(WebSecurity web) {
|
public void configure(WebSecurity web) {
|
||||||
// 忽略url
|
// 忽略url
|
||||||
WebSecurity.IgnoredRequestConfigurer ignoring = web.ignoring();
|
WebSecurity.IgnoredRequestConfigurer ignoring = web.ignoring();
|
||||||
List<String> noLoginUrlList = smartSecurityNoLoginUrl.getNoLoginUrlList();
|
List<String> ignoreUrlListList = smartSecurityUrlMatchers.getIgnoreUrlList();
|
||||||
for (String url : noLoginUrlList) {
|
for (String url : ignoreUrlListList) {
|
||||||
ignoring.antMatchers(url);
|
ignoring.antMatchers(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package net.lab1024.smartadmin.service.config;
|
package net.lab1024.smartadmin.service.config;
|
||||||
|
|
||||||
import net.lab1024.smartadmin.service.common.security.SmartSecurityMetadataSource;
|
import net.lab1024.smartadmin.service.common.security.SmartSecurityMetadataSource;
|
||||||
import net.lab1024.smartadmin.service.common.security.SmartSecurityNoLoginUrl;
|
import net.lab1024.smartadmin.service.common.security.SmartSecurityUrlMatchers;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.security.access.expression.method.ExpressionBasedAnnotationAttributeFactory;
|
import org.springframework.security.access.expression.method.ExpressionBasedAnnotationAttributeFactory;
|
||||||
@ -25,11 +25,11 @@ public class SecurityMethodConfig extends GlobalMethodSecurityConfiguration {
|
|||||||
* 无需登录的url
|
* 无需登录的url
|
||||||
*/
|
*/
|
||||||
@Autowired
|
@Autowired
|
||||||
private SmartSecurityNoLoginUrl smartSecurityNoLoginUrl;
|
private SmartSecurityUrlMatchers smartSecurityUrlMatchers;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MethodSecurityMetadataSource customMethodSecurityMetadataSource(){
|
public MethodSecurityMetadataSource customMethodSecurityMetadataSource(){
|
||||||
ExpressionBasedAnnotationAttributeFactory attributeFactory = new ExpressionBasedAnnotationAttributeFactory(this.getExpressionHandler());
|
ExpressionBasedAnnotationAttributeFactory attributeFactory = new ExpressionBasedAnnotationAttributeFactory(this.getExpressionHandler());
|
||||||
return new SmartSecurityMetadataSource(attributeFactory, smartSecurityNoLoginUrl.getNoLoginUrlList(),projectModule);
|
return new SmartSecurityMetadataSource(attributeFactory, smartSecurityUrlMatchers.getNoValidUrlList(),projectModule);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package net.lab1024.smartadmin.service.config;
|
package net.lab1024.smartadmin.service.config;
|
||||||
|
|
||||||
import net.lab1024.smartadmin.service.common.security.SmartSecurityNoLoginUrl;
|
import net.lab1024.smartadmin.service.common.security.SmartSecurityUrlMatchers;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@ -12,13 +12,13 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
* @date 2021/9/1 21:40
|
* @date 2021/9/1 21:40
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
public class SecurityNoLoginUrlConfig {
|
public class SecurityUrlConfig {
|
||||||
|
|
||||||
@Value("${project.module}")
|
@Value("${project.module}")
|
||||||
private String projectModule;
|
private String projectModule;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SmartSecurityNoLoginUrl securityNoLoginUrl(){
|
public SmartSecurityUrlMatchers securityUrl() {
|
||||||
return new SmartSecurityNoLoginUrl(projectModule);
|
return new SmartSecurityUrlMatchers(projectModule);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,17 +1,11 @@
|
|||||||
package net.lab1024.smartadmin.service.config;
|
package net.lab1024.smartadmin.service.config;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
|
||||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
|
||||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description
|
* @Description
|
||||||
* @Author 善逸
|
* @Author 善逸
|
||||||
@ -20,20 +14,9 @@ import java.util.Map.Entry;
|
|||||||
@Configuration
|
@Configuration
|
||||||
public class SmartWebAppConfig implements WebMvcConfigurer {
|
public class SmartWebAppConfig implements WebMvcConfigurer {
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private Map<String, HandlerInterceptor> interceptorMp;
|
|
||||||
|
|
||||||
@Value("${file.storage.local.path}")
|
@Value("${file.storage.local.path}")
|
||||||
private String localPath;
|
private String localPath;
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addInterceptors(InterceptorRegistry registry) {
|
|
||||||
for(Entry<String, HandlerInterceptor> entry : interceptorMp.entrySet()){
|
|
||||||
registry.addInterceptor(entry.getValue()).addPathPatterns(entry.getKey() + "/**");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addViewControllers(ViewControllerRegistry registry) {
|
public void addViewControllers(ViewControllerRegistry registry) {
|
||||||
registry.addViewController("/druidMonitor").setViewName("redirect:druid/index.html");
|
registry.addViewController("/druidMonitor").setViewName("redirect:druid/index.html");
|
||||||
@ -43,6 +26,6 @@ public class SmartWebAppConfig implements WebMvcConfigurer {
|
|||||||
@Override
|
@Override
|
||||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||||
registry.addResourceHandler("/**")
|
registry.addResourceHandler("/**")
|
||||||
.addResourceLocations("classpath:/META-INF/resources/","classpath:/resources/","classpath:/static/","file:" + localPath);
|
.addResourceLocations("classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "file:" + localPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,12 @@
|
|||||||
package net.lab1024.smartadmin.service.filters;
|
package net.lab1024.smartadmin.service.filter;
|
||||||
|
|
||||||
import net.lab1024.smartadmin.service.common.constant.CommonConst;
|
import net.lab1024.smartadmin.service.common.constant.CommonConst;
|
||||||
import net.lab1024.smartadmin.service.module.system.login.EmployeeLoginTokenService;
|
import net.lab1024.smartadmin.service.module.system.login.EmployeeLoginTokenService;
|
||||||
import net.lab1024.smartadmin.service.module.system.login.domain.EmployeeLoginBO;
|
import net.lab1024.smartadmin.service.module.system.login.domain.EmployeeLoginBO;
|
||||||
import net.lab1024.smartadmin.service.module.system.login.domain.EmployeeLoginInfoDTO;
|
|
||||||
import net.lab1024.smartadmin.service.util.SmartBeanUtil;
|
|
||||||
import net.lab1024.smartadmin.service.util.SmartEmployeeTokenUtil;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
import javax.servlet.FilterChain;
|
||||||
@ -21,15 +16,24 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* token过滤器
|
* [ ]
|
||||||
|
* 注意此处不能 加入@Component
|
||||||
|
* 否则对应ignoreUrl的相关请求 将会进入此Filter,并会覆盖CorsFilter
|
||||||
|
*
|
||||||
|
* @author 罗伊
|
||||||
|
* @date
|
||||||
*/
|
*/
|
||||||
@Component
|
|
||||||
public class SmartTokenFilter extends OncePerRequestFilter {
|
public class SmartSecurityTokenFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
private static final String TOKEN_NAME = "x-access-token";
|
private static final String TOKEN_NAME = "x-access-token";
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private EmployeeLoginTokenService loginTokenService;
|
private EmployeeLoginTokenService loginTokenService;
|
||||||
|
|
||||||
|
public SmartSecurityTokenFilter(EmployeeLoginTokenService loginTokenService) {
|
||||||
|
this.loginTokenService = loginTokenService;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
@ -38,28 +42,17 @@ public class SmartTokenFilter extends OncePerRequestFilter {
|
|||||||
String xRequestToken = request.getParameter(TOKEN_NAME);
|
String xRequestToken = request.getParameter(TOKEN_NAME);
|
||||||
String xAccessToken = null != xHeaderToken ? xHeaderToken : xRequestToken;
|
String xAccessToken = null != xHeaderToken ? xHeaderToken : xRequestToken;
|
||||||
if (StringUtils.isBlank(xAccessToken)) {
|
if (StringUtils.isBlank(xAccessToken)) {
|
||||||
// 若未给予spring security上下文用户授权 则会授权失败 进入AuthenticationEntryPointImpl
|
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
//清理spring security
|
||||||
// 先清理spring security上下文
|
|
||||||
SecurityContextHolder.clearContext();
|
SecurityContextHolder.clearContext();
|
||||||
|
EmployeeLoginBO loginBO = loginTokenService.getEmployeeLoginBO(xAccessToken);
|
||||||
// 判断请求分组
|
if (null != loginBO) {
|
||||||
String requestURI = request.getRequestURI();
|
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginBO, null, loginBO.getAuthorities());
|
||||||
if (StringUtils.startsWithIgnoreCase(requestURI, CommonConst.ApiUrl.API_PREFIX_ADMIN)) {
|
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||||
// 后管 获取用户信息
|
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
||||||
EmployeeLoginBO loginBO = loginTokenService.getEmployeeLoginBO(xAccessToken);
|
|
||||||
// 若获取到了登陆信息 则把用户信息设置到上下文中
|
|
||||||
if (null != loginBO) {
|
|
||||||
SmartEmployeeTokenUtil.setUser(SmartBeanUtil.copy(loginBO, EmployeeLoginInfoDTO.class));
|
|
||||||
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginBO, null, loginBO.getAuthorities());
|
|
||||||
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
|
||||||
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 若未给予spring security上下文用户授权 则会授权失败 进入AuthenticationEntryPointImpl
|
// 若未给予spring security上下文用户授权 则会授权失败 进入AuthenticationEntryPointImpl
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
}
|
}
|
@ -1,60 +0,0 @@
|
|||||||
package net.lab1024.smartadmin.service.interceptor;
|
|
||||||
|
|
||||||
import net.lab1024.smartadmin.service.common.constant.CommonConst;
|
|
||||||
import net.lab1024.smartadmin.service.util.SmartEmployeeTokenUtil;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [ 登录拦截器 ]
|
|
||||||
*
|
|
||||||
* @author 罗伊
|
|
||||||
*/
|
|
||||||
@Component(CommonConst.ApiUrl.API_PREFIX_ADMIN)
|
|
||||||
public class BusinessAuthorityInterceptor implements HandlerInterceptor {
|
|
||||||
|
|
||||||
@Value("${access-control-allow-origin}")
|
|
||||||
private String accessControlAllowOrigin;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 拦截服务器端响应处理ajax请求返回结果
|
|
||||||
*
|
|
||||||
* @param request
|
|
||||||
* @param response
|
|
||||||
* @param handler
|
|
||||||
* @return
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
|
||||||
//跨域设置
|
|
||||||
this.crossDomainConfig(response);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
|
|
||||||
SmartEmployeeTokenUtil.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 配置跨域
|
|
||||||
*
|
|
||||||
* @param response
|
|
||||||
*/
|
|
||||||
private void crossDomainConfig(HttpServletResponse response) {
|
|
||||||
response.setHeader("Access-Control-Allow-Origin", accessControlAllowOrigin);
|
|
||||||
response.setHeader("Access-Control-Allow-Credentials", "true");
|
|
||||||
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
|
|
||||||
response.setHeader("Access-Control-Expose-Headers", "*");
|
|
||||||
response.setHeader("Access-Control-Allow-Headers", "Authentication,Origin, X-Requested-With, Content-Type, " + "Accept, x-access-token");
|
|
||||||
response.setHeader("Cache-Control", "no-cache");
|
|
||||||
response.setHeader("Pragma", "no-cache");
|
|
||||||
response.setHeader("Expires ", "-1");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
package net.lab1024.smartadmin.service.interceptor;
|
|
||||||
|
|
||||||
import net.lab1024.smartadmin.service.common.constant.CommonConst;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 公用api 拦截器
|
|
||||||
*
|
|
||||||
* @author Administrator
|
|
||||||
*/
|
|
||||||
@Component(CommonConst.ApiUrl.API_PREFIX_SUPPORT)
|
|
||||||
public class SupportAuthorityInterceptor implements HandlerInterceptor {
|
|
||||||
|
|
||||||
@Value("${access-control-allow-origin}")
|
|
||||||
private String accessControlAllowOrigin;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 拦截服务器端响应处理ajax请求返回结果
|
|
||||||
*
|
|
||||||
* @param request
|
|
||||||
* @param response
|
|
||||||
* @param handler
|
|
||||||
* @return
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
|
||||||
//跨域设置
|
|
||||||
this.crossDomainConfig(response);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 配置跨域
|
|
||||||
*
|
|
||||||
* @param response
|
|
||||||
*/
|
|
||||||
private void crossDomainConfig(HttpServletResponse response) {
|
|
||||||
response.setHeader("Access-Control-Allow-Origin", accessControlAllowOrigin);
|
|
||||||
response.setHeader("Access-Control-Allow-Credentials", "true");
|
|
||||||
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
|
|
||||||
response.setHeader("Access-Control-Expose-Headers", "*");
|
|
||||||
response.setHeader("Access-Control-Allow-Headers", "Authentication,Origin, X-Requested-With, Content-Type, " + "Accept, x-access-token");
|
|
||||||
response.setHeader("Cache-Control", "no-cache");
|
|
||||||
response.setHeader("Pragma", "no-cache");
|
|
||||||
response.setHeader("Expires ", "-1");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
package net.lab1024.smartadmin.service.common.anno;
|
package net.lab1024.smartadmin.service.module.support.repeatsubmit;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
@ -2,7 +2,6 @@ package net.lab1024.smartadmin.service.module.support.repeatsubmit;
|
|||||||
|
|
||||||
import com.github.benmanes.caffeine.cache.Cache;
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
import net.lab1024.smartadmin.service.common.anno.NoRepeatSubmit;
|
|
||||||
import net.lab1024.smartadmin.service.common.codeconst.ResponseCodeConst;
|
import net.lab1024.smartadmin.service.common.codeconst.ResponseCodeConst;
|
||||||
import net.lab1024.smartadmin.service.common.domain.ResponseDTO;
|
import net.lab1024.smartadmin.service.common.domain.ResponseDTO;
|
||||||
import org.aspectj.lang.ProceedingJoinPoint;
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
@ -54,7 +53,7 @@ public class SmartRepeatSubmitAspect {
|
|||||||
* @return
|
* @return
|
||||||
* @throws Throwable
|
* @throws Throwable
|
||||||
*/
|
*/
|
||||||
@Around("@annotation(net.lab1024.smartadmin.service.common.anno.NoRepeatSubmit)")
|
@Around("@annotation(net.lab1024.smartadmin.service.module.support.repeatsubmit.NoRepeatSubmit)")
|
||||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||||
|
|
||||||
|
@ -1,22 +1,39 @@
|
|||||||
package net.lab1024.smartadmin.service.util;
|
package net.lab1024.smartadmin.service.util;
|
||||||
|
|
||||||
|
import net.lab1024.smartadmin.service.common.exception.SmartBusinessException;
|
||||||
import net.lab1024.smartadmin.service.module.system.login.domain.EmployeeLoginInfoDTO;
|
import net.lab1024.smartadmin.service.module.system.login.domain.EmployeeLoginInfoDTO;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author 罗伊
|
* @author 罗伊
|
||||||
*/
|
*/
|
||||||
public class SmartEmployeeTokenUtil {
|
public class SmartEmployeeTokenUtil {
|
||||||
|
|
||||||
private static final ThreadLocal<EmployeeLoginInfoDTO> LOCAL_USER = new ThreadLocal<>();
|
/**
|
||||||
|
* 获取用户信息
|
||||||
public static void setUser(EmployeeLoginInfoDTO loginInfoDTO) {
|
* @return
|
||||||
LOCAL_USER.set(loginInfoDTO);
|
*/
|
||||||
}
|
|
||||||
|
|
||||||
public static EmployeeLoginInfoDTO getRequestEmployee() {
|
public static EmployeeLoginInfoDTO getRequestEmployee() {
|
||||||
return LOCAL_USER.get();
|
try {
|
||||||
|
return (EmployeeLoginInfoDTO) getAuthentication().getPrincipal();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new SmartBusinessException("获取用户信息异常");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户认证信息
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Authentication getAuthentication() {
|
||||||
|
return SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public static Long getRequestEmployeeId() {
|
public static Long getRequestEmployeeId() {
|
||||||
EmployeeLoginInfoDTO requestUser = getRequestEmployee();
|
EmployeeLoginInfoDTO requestUser = getRequestEmployee();
|
||||||
if (null == requestUser) {
|
if (null == requestUser) {
|
||||||
@ -24,8 +41,4 @@ public class SmartEmployeeTokenUtil {
|
|||||||
}
|
}
|
||||||
return requestUser.getEmployeeId();
|
return requestUser.getEmployeeId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void remove() {
|
|
||||||
LOCAL_USER.remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user