mirror of
https://gitee.com/y_project/RuoYi-Cloud.git
synced 2026-01-28 12:41:55 +08:00
若依 1.0
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
package com.ruoyi.common.security.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
// 表示通过aop框架暴露该代理对象,AopContext能够访问
|
||||
@EnableAspectJAutoProxy(exposeProxy = true)
|
||||
// 指定要扫描的Mapper类的包的路径
|
||||
@MapperScan("com.ruoyi.**.mapper")
|
||||
// 开启线程异步执行
|
||||
@EnableAsync
|
||||
public @interface EnableCustomConfig
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.ruoyi.common.security.annotation;
|
||||
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 自定义feign注解
|
||||
* 添加basePackages路径
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@EnableFeignClients
|
||||
public @interface EnableRyFeignClients
|
||||
{
|
||||
String[] value() default {};
|
||||
|
||||
String[] basePackages() default { "com.ruoyi" };
|
||||
|
||||
Class<?>[] basePackageClasses() default {};
|
||||
|
||||
Class<?>[] defaultConfiguration() default {};
|
||||
|
||||
Class<?>[] clients() default {};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.ruoyi.common.security.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
|
||||
import com.ruoyi.common.security.component.RyResourceServerAutoConfiguration;
|
||||
import com.ruoyi.common.security.component.RySecurityBeanDefinitionRegistrar;
|
||||
|
||||
/**
|
||||
* 自定义资源服务注解
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Documented
|
||||
@Inherited
|
||||
@EnableResourceServer
|
||||
@Target({ ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
@Import({ RyResourceServerAutoConfiguration.class, RySecurityBeanDefinitionRegistrar.class })
|
||||
public @interface EnableRyResourceServer
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.ruoyi.common.security.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 服务调用不鉴权注解
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Inner
|
||||
{
|
||||
/**
|
||||
* 是否AOP统一处理
|
||||
*/
|
||||
boolean value() default true;
|
||||
|
||||
/**
|
||||
* 需要特殊判空的字段(预留)
|
||||
*/
|
||||
String[] field() default {};
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.ruoyi.common.security.aspect;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.ruoyi.common.core.constant.SecurityConstants;
|
||||
import com.ruoyi.common.core.utils.ServletUtils;
|
||||
import com.ruoyi.common.core.utils.StringUtils;
|
||||
import com.ruoyi.common.security.annotation.Inner;
|
||||
|
||||
/**
|
||||
* 服务间接口不鉴权处理逻辑
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class InnerAspect implements Ordered
|
||||
{
|
||||
private final Logger log = LoggerFactory.getLogger(InnerAspect.class);
|
||||
|
||||
@Around("@annotation(inner)")
|
||||
public Object around(ProceedingJoinPoint point, Inner inner) throws Throwable
|
||||
{
|
||||
String header = ServletUtils.getRequest().getHeader(SecurityConstants.FROM);
|
||||
if (inner.value() && !StringUtils.equals(SecurityConstants.FROM_IN, header))
|
||||
{
|
||||
log.warn("访问接口 {} 没有权限", point.getSignature().getName());
|
||||
throw new AccessDeniedException("Access is denied");
|
||||
}
|
||||
return point.proceed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder()
|
||||
{
|
||||
return Ordered.HIGHEST_PRECEDENCE + 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.ruoyi.common.security.component;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.ruoyi.common.core.constant.HttpStatus;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.utils.ServletUtils;
|
||||
|
||||
/**
|
||||
* 自定义认证失败的异常
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class ResourceAuthExceptionEntryPoint implements AuthenticationEntryPoint
|
||||
{
|
||||
private final Logger logger = LoggerFactory.getLogger(ResourceAuthExceptionEntryPoint.class);
|
||||
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException authException) throws IOException
|
||||
{
|
||||
logger.info("令牌不合法,禁止访问 {}", request.getRequestURI());
|
||||
|
||||
String msg = authException.getMessage();
|
||||
ServletUtils.renderString(response, JSON.toJSONString(R.failed(HttpStatus.UNAUTHORIZED, msg)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.ruoyi.common.security.component;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@ConfigurationPropertiesScan
|
||||
@ComponentScan("com.ruoyi.common.security")
|
||||
public class RyResourceServerAutoConfiguration
|
||||
{
|
||||
@Bean
|
||||
@Primary
|
||||
@LoadBalanced
|
||||
public RestTemplate lbRestTemplate()
|
||||
{
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
restTemplate.setErrorHandler(new DefaultResponseErrorHandler()
|
||||
{
|
||||
@Override
|
||||
public void handleError(ClientHttpResponse response) throws IOException
|
||||
{
|
||||
if (response.getRawStatusCode() != HttpStatus.BAD_REQUEST.value())
|
||||
{
|
||||
super.handleError(response);
|
||||
}
|
||||
}
|
||||
});
|
||||
return restTemplate;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.ruoyi.common.security.component;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
|
||||
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
|
||||
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
|
||||
import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import com.ruoyi.common.security.component.properties.PermitAllUrlProperties;
|
||||
|
||||
public class RyResourceServerConfigurerAdapter extends ResourceServerConfigurerAdapter
|
||||
{
|
||||
@Autowired
|
||||
protected ResourceAuthExceptionEntryPoint resourceAuthExceptionEntryPoint;
|
||||
|
||||
@Autowired
|
||||
protected RemoteTokenServices remoteTokenServices;
|
||||
|
||||
@Autowired
|
||||
private AccessDeniedHandler accessDeniedHandler;
|
||||
|
||||
@Autowired
|
||||
private PermitAllUrlProperties permitAllUrl;
|
||||
|
||||
@Autowired
|
||||
private RestTemplate lbRestTemplate;
|
||||
|
||||
/**
|
||||
* 默认的配置,对外暴露
|
||||
*
|
||||
* @param httpSecurity
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public void configure(HttpSecurity httpSecurity) throws Exception
|
||||
{
|
||||
//允许使用iframe 嵌套,避免swagger-ui 不被加载的问题
|
||||
httpSecurity.headers().frameOptions().disable();
|
||||
ExpressionUrlAuthorizationConfigurer<HttpSecurity>
|
||||
.ExpressionInterceptUrlRegistry registry = httpSecurity
|
||||
.authorizeRequests();
|
||||
permitAllUrl.getUrls()
|
||||
.forEach(url -> registry.antMatchers(url).permitAll());
|
||||
registry.anyRequest().authenticated()
|
||||
.and().csrf().disable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(ResourceServerSecurityConfigurer resources)
|
||||
{
|
||||
DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
|
||||
UserAuthenticationConverter userTokenConverter = new RyUserAuthenticationConverter();
|
||||
accessTokenConverter.setUserTokenConverter(userTokenConverter);
|
||||
|
||||
remoteTokenServices.setRestTemplate(lbRestTemplate);
|
||||
remoteTokenServices.setAccessTokenConverter(accessTokenConverter);
|
||||
resources.authenticationEntryPoint(resourceAuthExceptionEntryPoint).accessDeniedHandler(accessDeniedHandler)
|
||||
.tokenServices(remoteTokenServices);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.ruoyi.common.security.component;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.AllNestedConditions;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration;
|
||||
import org.springframework.cloud.security.oauth2.client.AccessTokenContextRelay;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.oauth2.client.OAuth2ClientContext;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.OAuth2ClientConfiguration;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfiguration;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Configuration
|
||||
@AutoConfigureAfter(OAuth2AutoConfiguration.class)
|
||||
@ConditionalOnWebApplication
|
||||
@ConditionalOnProperty("security.oauth2.client.client-id")
|
||||
public class RyResourceServerTokenRelayAutoConfiguration
|
||||
{
|
||||
@Bean
|
||||
public AccessTokenContextRelay accessTokenContextRelay(OAuth2ClientContext context)
|
||||
{
|
||||
return new AccessTokenContextRelay(context);
|
||||
}
|
||||
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Conditional(OAuth2OnClientInResourceServerCondition.class)
|
||||
@interface ConditionalOnOAuth2ClientInResourceServer
|
||||
{
|
||||
}
|
||||
|
||||
private static class OAuth2OnClientInResourceServerCondition extends AllNestedConditions
|
||||
{
|
||||
public OAuth2OnClientInResourceServerCondition()
|
||||
{
|
||||
super(ConfigurationPhase.REGISTER_BEAN);
|
||||
}
|
||||
|
||||
@ConditionalOnBean(ResourceServerConfiguration.class)
|
||||
static class Server
|
||||
{
|
||||
}
|
||||
|
||||
@ConditionalOnBean(OAuth2ClientConfiguration.class)
|
||||
static class Client
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.ruoyi.common.security.component;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import com.ruoyi.common.core.constant.SecurityConstants;
|
||||
|
||||
public class RySecurityBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar
|
||||
{
|
||||
private final Logger log = LoggerFactory.getLogger(RySecurityBeanDefinitionRegistrar.class);
|
||||
|
||||
/**
|
||||
* 根据注解值动态注入资源服务器的相关属性
|
||||
*
|
||||
* @param metadata 注解信息
|
||||
* @param registry 注册器
|
||||
*/
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry)
|
||||
{
|
||||
if (registry.isBeanNameInUse(SecurityConstants.RESOURCE_SERVER_CONFIGURER))
|
||||
{
|
||||
log.warn("本地存在资源服务器配置,覆盖默认配置:" + SecurityConstants.RESOURCE_SERVER_CONFIGURER);
|
||||
return;
|
||||
}
|
||||
|
||||
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
|
||||
beanDefinition.setBeanClass(RyResourceServerConfigurerAdapter.class);
|
||||
registry.registerBeanDefinition(SecurityConstants.RESOURCE_SERVER_CONFIGURER, beanDefinition);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.ruoyi.common.security.component;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter;
|
||||
import org.springframework.util.StringUtils;
|
||||
import com.ruoyi.common.core.constant.SecurityConstants;
|
||||
import com.ruoyi.common.core.text.Convert;
|
||||
import com.ruoyi.common.security.domain.LoginUser;
|
||||
|
||||
/**
|
||||
* 根据checktoken 的结果转化用户信息
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class RyUserAuthenticationConverter implements UserAuthenticationConverter
|
||||
{
|
||||
private static final String N_A = "N/A";
|
||||
|
||||
@Override
|
||||
public Map<String, ?> convertUserAuthentication(Authentication authentication)
|
||||
{
|
||||
Map<String, Object> response = new LinkedHashMap<>();
|
||||
response.put(USERNAME, authentication.getName());
|
||||
if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty())
|
||||
{
|
||||
response.put(AUTHORITIES, AuthorityUtils.authorityListToSet(authentication.getAuthorities()));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication extractAuthentication(Map<String, ?> map)
|
||||
{
|
||||
if (map.containsKey(USERNAME))
|
||||
{
|
||||
Collection<? extends GrantedAuthority> authorities = getAuthorities(map);
|
||||
|
||||
String username = (String) map.get(SecurityConstants.DETAILS_USERNAME);
|
||||
Long id = Convert.toLong(map.get(SecurityConstants.DETAILS_USER_ID));
|
||||
Long deptId = Convert.toLong(map.get(SecurityConstants.DETAILS_DEPT_ID));
|
||||
LoginUser user = new LoginUser(id, deptId, username, N_A, true, true, true, true, authorities);
|
||||
return new UsernamePasswordAuthenticationToken(user, N_A, authorities);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Collection<? extends GrantedAuthority> getAuthorities(Map<String, ?> map)
|
||||
{
|
||||
Object authorities = map.get(AUTHORITIES);
|
||||
if (authorities instanceof String)
|
||||
{
|
||||
return AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities);
|
||||
}
|
||||
if (authorities instanceof Collection)
|
||||
{
|
||||
return AuthorityUtils.commaSeparatedStringToAuthorityList(
|
||||
StringUtils.collectionToCommaDelimitedString((Collection<?>) authorities));
|
||||
}
|
||||
throw new IllegalArgumentException("Authorities must be either a String or a Collection");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.ruoyi.common.security.component;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
|
||||
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
|
||||
|
||||
/**
|
||||
* OAuth2 自定义异常处理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class RyWebResponseExceptionTranslator implements WebResponseExceptionTranslator<OAuth2Exception>
|
||||
{
|
||||
private final Logger logger = LoggerFactory.getLogger(RyWebResponseExceptionTranslator.class);
|
||||
|
||||
@Override
|
||||
public ResponseEntity<OAuth2Exception> translate(Exception e)
|
||||
{
|
||||
OAuth2Exception oAuth2Exception = (OAuth2Exception) e;
|
||||
logger.error("RyWebResponseExceptionTranslator.status:{},oAuth2ErrorCode:{},message:{}",
|
||||
oAuth2Exception.getHttpErrorCode(), oAuth2Exception.getOAuth2ErrorCode(), oAuth2Exception.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(oAuth2Exception);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.ruoyi.common.security.component.properties;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import com.ruoyi.common.core.utils.ReUtil;
|
||||
import com.ruoyi.common.security.annotation.Inner;
|
||||
|
||||
/**
|
||||
* 资源服务器对外直接暴露url
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "security.oauth2.ignore")
|
||||
public class PermitAllUrlProperties implements InitializingBean, ApplicationContextAware
|
||||
{
|
||||
private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private List<String> urls = new ArrayList<>();
|
||||
|
||||
public String ASTERISK = "*";
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet()
|
||||
{
|
||||
RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
|
||||
Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
|
||||
|
||||
map.keySet().forEach(info -> {
|
||||
HandlerMethod handlerMethod = map.get(info);
|
||||
|
||||
// 获取方法上边的注解 替代path variable 为 *
|
||||
Inner method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Inner.class);
|
||||
Optional.ofNullable(method).ifPresent(inner -> info.getPatternsCondition().getPatterns()
|
||||
.forEach(url -> urls.add(ReUtil.replaceAll(url, PATTERN, ASTERISK))));
|
||||
|
||||
// 获取类上边的注解, 替代path variable 为 *
|
||||
Inner controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Inner.class);
|
||||
Optional.ofNullable(controller).ifPresent(inner -> info.getPatternsCondition().getPatterns()
|
||||
.forEach(url -> urls.add(ReUtil.replaceAll(url, PATTERN, ASTERISK))));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext context) throws BeansException
|
||||
{
|
||||
this.applicationContext = context;
|
||||
}
|
||||
|
||||
public List<String> getUrls()
|
||||
{
|
||||
return urls;
|
||||
}
|
||||
|
||||
public void setUrls(List<String> urls)
|
||||
{
|
||||
this.urls = urls;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.ruoyi.common.security.domain;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
|
||||
/**
|
||||
* 登录用户身份权限
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class LoginUser extends User
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
public LoginUser(Long userId, Long deptId, String username, String password, boolean enabled,
|
||||
boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked,
|
||||
Collection<? extends GrantedAuthority> authorities)
|
||||
{
|
||||
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
|
||||
this.userId = userId;
|
||||
this.deptId = deptId;
|
||||
}
|
||||
|
||||
public Long getUserId()
|
||||
{
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(Long userId)
|
||||
{
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public Long getDeptId()
|
||||
{
|
||||
return deptId;
|
||||
}
|
||||
|
||||
public void setDeptId(Long deptId)
|
||||
{
|
||||
this.deptId = deptId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.ruoyi.common.security.feign;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import feign.RequestInterceptor;
|
||||
|
||||
/**
|
||||
* Feign配置注册
|
||||
*
|
||||
* @author ruoyi
|
||||
**/
|
||||
@Configuration
|
||||
public class OAuth2FeignConfig
|
||||
{
|
||||
@Bean
|
||||
public RequestInterceptor requestInterceptor()
|
||||
{
|
||||
return new OAuth2FeignRequestInterceptor();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.ruoyi.common.security.feign;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.ruoyi.common.core.constant.SecurityConstants;
|
||||
import com.ruoyi.common.core.utils.StringUtils;
|
||||
import feign.RequestInterceptor;
|
||||
import feign.RequestTemplate;
|
||||
|
||||
/**
|
||||
* feign请求拦截器
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class OAuth2FeignRequestInterceptor implements RequestInterceptor
|
||||
{
|
||||
private final String AUTHORIZATION_HEADER = "Authorization";
|
||||
|
||||
private final String BEARER_TOKEN_TYPE = "Bearer";
|
||||
|
||||
@Override
|
||||
public void apply(RequestTemplate requestTemplate)
|
||||
{
|
||||
Collection<String> fromHeader = requestTemplate.headers().get(SecurityConstants.FROM);
|
||||
if (StringUtils.isNotEmpty(fromHeader) && fromHeader.contains(SecurityConstants.FROM_IN))
|
||||
{
|
||||
return;
|
||||
}
|
||||
SecurityContext securityContext = SecurityContextHolder.getContext();
|
||||
Authentication authentication = securityContext.getAuthentication();
|
||||
if (authentication != null && authentication.getDetails() instanceof OAuth2AuthenticationDetails)
|
||||
{
|
||||
OAuth2AuthenticationDetails dateils = (OAuth2AuthenticationDetails) authentication.getDetails();
|
||||
requestTemplate.header(AUTHORIZATION_HEADER,
|
||||
String.format("%s %s", BEARER_TOKEN_TYPE, dateils.getTokenValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.ruoyi.common.security.handler;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
|
||||
/**
|
||||
* 认证失败事件处理器
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public abstract class AbstractAuthenticationFailureEvenHandler
|
||||
implements ApplicationListener<AbstractAuthenticationFailureEvent>
|
||||
{
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(AbstractAuthenticationFailureEvent event)
|
||||
{
|
||||
AuthenticationException authenticationException = event.getException();
|
||||
Authentication authentication = (Authentication) event.getSource();
|
||||
|
||||
handle(authenticationException, authentication);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理登录失败方法
|
||||
*/
|
||||
public abstract void handle(AuthenticationException authenticationException, Authentication authentication);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.ruoyi.common.security.handler;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import com.ruoyi.common.core.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 认证成功事件处理器
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public abstract class AbstractAuthenticationSuccessEventHandler
|
||||
implements ApplicationListener<AuthenticationSuccessEvent>
|
||||
{
|
||||
@Override
|
||||
public void onApplicationEvent(AuthenticationSuccessEvent event)
|
||||
{
|
||||
Authentication authentication = (Authentication) event.getSource();
|
||||
if (StringUtils.isNotEmpty(authentication.getAuthorities()))
|
||||
{
|
||||
handle(authentication);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理登录成功方法
|
||||
*/
|
||||
public abstract void handle(Authentication authentication);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.ruoyi.common.security.handler;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.ruoyi.common.core.constant.HttpStatus;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.utils.ServletUtils;
|
||||
|
||||
/**
|
||||
* 自定义访问无权限资源时的异常
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class CustomAccessDeniedHandler extends OAuth2AccessDeniedHandler
|
||||
{
|
||||
private final Logger logger = LoggerFactory.getLogger(CustomAccessDeniedHandler.class);
|
||||
|
||||
@Override
|
||||
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException authException)
|
||||
{
|
||||
logger.info("权限不足,请联系管理员 {}", request.getRequestURI());
|
||||
|
||||
String msg = authException.getMessage();
|
||||
ServletUtils.renderString(response, JSON.toJSONString(R.failed(HttpStatus.FORBIDDEN, msg)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
package com.ruoyi.common.security.service;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import com.ruoyi.common.security.domain.LoginUser;
|
||||
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||
|
||||
/**
|
||||
* RuoYi首创 自定义权限实现,ss取自SpringSecurity首字母
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Service("ss")
|
||||
public class PermissionService
|
||||
{
|
||||
/** 所有权限标识 */
|
||||
private static final String ALL_PERMISSION = "*:*:*";
|
||||
|
||||
/** 管理员角色权限标识 */
|
||||
private static final String SUPER_ADMIN = "admin";
|
||||
|
||||
private static final String ROLE_DELIMETER = ",";
|
||||
|
||||
private static final String PERMISSION_DELIMETER = ",";
|
||||
|
||||
/**
|
||||
* 验证用户是否具备某权限
|
||||
*
|
||||
* @param permission 权限字符串
|
||||
* @return 用户是否具备某权限
|
||||
*/
|
||||
public boolean hasPermi(String permission)
|
||||
{
|
||||
if (StringUtils.isEmpty(permission))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
if (StringUtils.isEmpty(loginUser) || CollectionUtils.isEmpty(loginUser.getAuthorities()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return hasPermissions(loginUser.getAuthorities(), permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户是否不具备某权限,与 hasPermi逻辑相反
|
||||
*
|
||||
* @param permission 权限字符串
|
||||
* @return 用户是否不具备某权限
|
||||
*/
|
||||
public boolean lacksPermi(String permission)
|
||||
{
|
||||
return hasPermi(permission) != true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户是否具有以下任意一个权限
|
||||
*
|
||||
* @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
|
||||
* @return 用户是否具有以下任意一个权限
|
||||
*/
|
||||
public boolean hasAnyPermi(String permissions)
|
||||
{
|
||||
if (StringUtils.isEmpty(permissions))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
if (StringUtils.isEmpty(loginUser) || CollectionUtils.isEmpty(loginUser.getAuthorities()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Collection<? extends GrantedAuthority> authorities = loginUser.getAuthorities();
|
||||
for (String permission : permissions.split(PERMISSION_DELIMETER))
|
||||
{
|
||||
if (permission != null && hasPermissions(authorities, permission))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断用户是否拥有某个角色
|
||||
*
|
||||
* @param role 角色字符串
|
||||
* @return 用户是否具备某角色
|
||||
*/
|
||||
public boolean hasRole(String role)
|
||||
{
|
||||
if (StringUtils.isEmpty(role))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
if (StringUtils.isEmpty(loginUser) || CollectionUtils.isEmpty(loginUser.getAuthorities()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (GrantedAuthority authorities : loginUser.getAuthorities())
|
||||
{
|
||||
String roleKey = authorities.getAuthority();
|
||||
if (SUPER_ADMIN.contains(roleKey) || roleKey.contains(role))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户是否不具备某角色,与 isRole逻辑相反。
|
||||
*
|
||||
* @param role 角色名称
|
||||
* @return 用户是否不具备某角色
|
||||
*/
|
||||
public boolean lacksRole(String role)
|
||||
{
|
||||
return hasRole(role) != true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户是否具有以下任意一个角色
|
||||
*
|
||||
* @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
|
||||
* @return 用户是否具有以下任意一个角色
|
||||
*/
|
||||
public boolean hasAnyRoles(String roles)
|
||||
{
|
||||
if (StringUtils.isEmpty(roles))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
if (StringUtils.isEmpty(loginUser) || CollectionUtils.isEmpty(loginUser.getAuthorities()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (String role : roles.split(ROLE_DELIMETER))
|
||||
{
|
||||
if (hasRole(role))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否包含权限
|
||||
*
|
||||
* @param permissions 权限列表
|
||||
* @param permission 权限字符串
|
||||
* @return 用户是否具备某权限
|
||||
*/
|
||||
private boolean hasPermissions(Collection<? extends GrantedAuthority> authorities, String permission)
|
||||
{
|
||||
return authorities.stream().map(GrantedAuthority::getAuthority).filter(StringUtils::hasText)
|
||||
.anyMatch(x -> ALL_PERMISSION.contains(x) || PatternMatchUtils.simpleMatch(permission, x));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.ruoyi.common.security.service;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.security.oauth2.provider.ClientDetails;
|
||||
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
|
||||
import com.ruoyi.common.core.constant.CacheConstants;
|
||||
|
||||
/**
|
||||
* 重写原生方法支持redis缓存
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class RedisClientDetailsService extends JdbcClientDetailsService
|
||||
{
|
||||
public RedisClientDetailsService(DataSource dataSource)
|
||||
{
|
||||
super(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(value = CacheConstants.CLIENT_DETAILS_KEY, key = "#clientId", unless = "#result == null")
|
||||
public ClientDetails loadClientByClientId(String clientId)
|
||||
{
|
||||
return super.loadClientByClientId(clientId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.ruoyi.common.security.service;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.ruoyi.common.core.constant.SecurityConstants;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.enums.UserStatus;
|
||||
import com.ruoyi.common.core.exception.BaseException;
|
||||
import com.ruoyi.common.core.utils.StringUtils;
|
||||
import com.ruoyi.common.security.domain.LoginUser;
|
||||
import com.ruoyi.system.api.RemoteUserService;
|
||||
import com.ruoyi.system.api.domain.SysUser;
|
||||
import com.ruoyi.system.api.model.UserInfo;
|
||||
|
||||
/**
|
||||
* 用户详细信息
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Service
|
||||
public class UserDetailsServiceImpl implements UserDetailsService
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
|
||||
|
||||
@Autowired
|
||||
private RemoteUserService remoteUserService;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username)
|
||||
{
|
||||
R<UserInfo> userResult = remoteUserService.info(username, SecurityConstants.FROM_IN);
|
||||
checkUser(userResult, username);
|
||||
return getUserDetails(userResult);
|
||||
}
|
||||
|
||||
public void checkUser(R<UserInfo> userResult, String username)
|
||||
{
|
||||
if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData()))
|
||||
{
|
||||
log.info("登录用户:{} 不存在.", username);
|
||||
throw new UsernameNotFoundException("登录用户:" + username + " 不存在");
|
||||
}
|
||||
else if (UserStatus.DELETED.getCode().equals(userResult.getData().getSysUser().getDelFlag()))
|
||||
{
|
||||
log.info("登录用户:{} 已被删除.", username);
|
||||
throw new BaseException("对不起,您的账号:" + username + " 已被删除");
|
||||
}
|
||||
else if (UserStatus.DISABLE.getCode().equals(userResult.getData().getSysUser().getStatus()))
|
||||
{
|
||||
log.info("登录用户:{} 已被停用.", username);
|
||||
throw new BaseException("对不起,您的账号:" + username + " 已停用");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建userdetails
|
||||
*
|
||||
* @param result 用户信息
|
||||
* @return
|
||||
*/
|
||||
private UserDetails getUserDetails(R<UserInfo> result)
|
||||
{
|
||||
UserInfo info = result.getData();
|
||||
Set<String> dbAuthsSet = new HashSet<String>();
|
||||
if (StringUtils.isNotEmpty(info.getRoles()))
|
||||
{
|
||||
// 获取角色
|
||||
Arrays.stream(info.getRoles()).forEach(role -> dbAuthsSet.add(role));
|
||||
// 获取资源
|
||||
dbAuthsSet.addAll(Arrays.asList(info.getPermissions()));
|
||||
}
|
||||
|
||||
Collection<? extends GrantedAuthority> authorities = AuthorityUtils
|
||||
.createAuthorityList(dbAuthsSet.toArray(new String[0]));
|
||||
SysUser user = info.getSysUser();
|
||||
|
||||
// 构造security用户
|
||||
return new LoginUser(user.getUserId(), user.getDeptId(), user.getUserName(), user.getPassword(), true, true,
|
||||
true, true, authorities);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.ruoyi.common.security.utils;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import com.ruoyi.common.security.domain.LoginUser;
|
||||
|
||||
/**
|
||||
* 权限获取工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class SecurityUtils
|
||||
{
|
||||
/**
|
||||
* 获取Authentication
|
||||
*/
|
||||
public static Authentication getAuthentication()
|
||||
{
|
||||
return SecurityContextHolder.getContext().getAuthentication();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户
|
||||
*/
|
||||
public static String getUsername()
|
||||
{
|
||||
return getLoginUser().getUsername();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户
|
||||
*/
|
||||
public static LoginUser getLoginUser(Authentication authentication)
|
||||
{
|
||||
Object principal = authentication.getPrincipal();
|
||||
if (principal instanceof LoginUser)
|
||||
{
|
||||
return (LoginUser) principal;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户
|
||||
*/
|
||||
public static LoginUser getLoginUser()
|
||||
{
|
||||
Authentication authentication = getAuthentication();
|
||||
if (authentication == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return getLoginUser(authentication);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成BCryptPasswordEncoder密码
|
||||
*
|
||||
* @param password 密码
|
||||
* @return 加密字符串
|
||||
*/
|
||||
public static String encryptPassword(String password)
|
||||
{
|
||||
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||
return passwordEncoder.encode(password);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断密码是否相同
|
||||
*
|
||||
* @param rawPassword 真实密码
|
||||
* @param encodedPassword 加密后字符
|
||||
* @return 结果
|
||||
*/
|
||||
public static boolean matchesPassword(String rawPassword, String encodedPassword)
|
||||
{
|
||||
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||
return passwordEncoder.matches(rawPassword, encodedPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为管理员
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 结果
|
||||
*/
|
||||
public static boolean isAdmin(Long userId)
|
||||
{
|
||||
return userId != null && 1L == userId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.ruoyi.common.security.service.UserDetailsServiceImpl,\
|
||||
com.ruoyi.common.security.handler.CustomAccessDeniedHandler,\
|
||||
com.ruoyi.common.security.component.ResourceAuthExceptionEntryPoint,\
|
||||
com.ruoyi.common.security.aspect.InnerAspect
|
||||
|
||||
|
||||
Reference in New Issue
Block a user