mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-26 01:01:52 +08:00
增加 @PreAuthenticated 注解,实现登陆的拦截
This commit is contained in:
parent
0439a5505a
commit
689171c18d
2
pom.xml
2
pom.xml
@ -19,7 +19,7 @@
|
|||||||
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<revision>1.0.0-snapshot</revision>
|
<revision>1.1.0-snapshot</revision>
|
||||||
<!-- Maven 相关 -->
|
<!-- Maven 相关 -->
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
package cn.iocoder.yudao.adminserver.framework.security;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class SecurityConfiguration {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private WebProperties webProperties;
|
||||||
|
|
||||||
|
@Value("${spring.boot.admin.context-path:''}")
|
||||||
|
private String adminSeverContextPath;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer() {
|
||||||
|
return registry -> {
|
||||||
|
// 通用的接口,可匿名访问 TODO 芋艿:需要抽象出去
|
||||||
|
registry.antMatchers(api("/system/captcha/**")).anonymous();
|
||||||
|
// Spring Boot Admin Server 的安全配置 TODO 芋艿:需要抽象出去
|
||||||
|
registry.antMatchers(adminSeverContextPath).anonymous()
|
||||||
|
.antMatchers(adminSeverContextPath + "/**").anonymous();
|
||||||
|
// 短信回调 API
|
||||||
|
registry.antMatchers(api("/system/sms/callback/**")).anonymous();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private String api(String url) {
|
||||||
|
return webProperties.getApiPrefix() + url;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -19,7 +19,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.iocoder.boot</groupId>
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
<artifactId>yudao-common</artifactId>
|
<artifactId>yudao-common</artifactId>
|
||||||
<version>${revision}</version>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Spring 核心 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-aop</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Web 相关 -->
|
<!-- Web 相关 -->
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package cn.iocoder.yudao.framework.security.config;
|
package cn.iocoder.yudao.framework.security.config;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.security.core.aop.PreAuthenticatedAspect;
|
||||||
import cn.iocoder.yudao.framework.security.core.filter.JwtAuthenticationTokenFilter;
|
import cn.iocoder.yudao.framework.security.core.filter.JwtAuthenticationTokenFilter;
|
||||||
import cn.iocoder.yudao.framework.security.core.handler.AccessDeniedHandlerImpl;
|
import cn.iocoder.yudao.framework.security.core.handler.AccessDeniedHandlerImpl;
|
||||||
import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPointImpl;
|
import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPointImpl;
|
||||||
@ -32,6 +33,14 @@ public class YudaoSecurityAutoConfiguration {
|
|||||||
@Resource
|
@Resource
|
||||||
private SecurityProperties securityProperties;
|
private SecurityProperties securityProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理用户未登陆拦截的切面的 Bean
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public PreAuthenticatedAspect preAuthenticatedAspect() {
|
||||||
|
return new PreAuthenticatedAspect();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 认证失败处理类 Bean
|
* 认证失败处理类 Bean
|
||||||
*/
|
*/
|
||||||
|
@ -14,10 +14,12 @@ import org.springframework.context.annotation.Bean;
|
|||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||||
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.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.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
@ -41,9 +43,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
|
|||||||
@Resource
|
@Resource
|
||||||
private WebProperties webProperties;
|
private WebProperties webProperties;
|
||||||
|
|
||||||
@Value("${spring.boot.admin.context-path:''}")
|
|
||||||
private String adminSeverContextPath;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义用户【认证】逻辑
|
* 自定义用户【认证】逻辑
|
||||||
*/
|
*/
|
||||||
@ -74,6 +73,13 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
|
|||||||
*/
|
*/
|
||||||
@Resource
|
@Resource
|
||||||
private JwtAuthenticationTokenFilter authenticationTokenFilter;
|
private JwtAuthenticationTokenFilter authenticationTokenFilter;
|
||||||
|
/**
|
||||||
|
* 自定义的权限映射 Bean
|
||||||
|
*
|
||||||
|
* @see #configure(HttpSecurity)
|
||||||
|
*/
|
||||||
|
@Resource
|
||||||
|
private Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 由于 Spring Security 创建 AuthenticationManager 对象时,没声明 @Bean 注解,导致无法被注入
|
* 由于 Spring Security 创建 AuthenticationManager 对象时,没声明 @Bean 注解,导致无法被注入
|
||||||
@ -121,15 +127,16 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
|
|||||||
.csrf().disable()
|
.csrf().disable()
|
||||||
// 基于 token 机制,所以不需要 Session
|
// 基于 token 机制,所以不需要 Session
|
||||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
|
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
|
||||||
|
.headers().frameOptions().disable().and()
|
||||||
// 一堆自定义的 Spring Security 处理器
|
// 一堆自定义的 Spring Security 处理器
|
||||||
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
|
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
|
||||||
.accessDeniedHandler(accessDeniedHandler).and()
|
.accessDeniedHandler(accessDeniedHandler).and()
|
||||||
// 设置每个请求的权限
|
.logout().logoutUrl(api("/logout")).logoutSuccessHandler(logoutSuccessHandler); // 登出
|
||||||
.authorizeRequests()
|
|
||||||
|
// 设置每个请求的权限 ①:全局共享规则
|
||||||
|
httpSecurity.authorizeRequests()
|
||||||
// 登陆的接口,可匿名访问
|
// 登陆的接口,可匿名访问
|
||||||
.antMatchers(api("/login")).anonymous()
|
.antMatchers(api("/login")).anonymous()
|
||||||
// 通用的接口,可匿名访问 TODO 芋艿:需要抽象出去
|
|
||||||
.antMatchers(api("/system/captcha/**")).anonymous()
|
|
||||||
// 静态资源,可匿名访问
|
// 静态资源,可匿名访问
|
||||||
.antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
|
.antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
|
||||||
// 文件的获取接口,可匿名访问
|
// 文件的获取接口,可匿名访问
|
||||||
@ -139,22 +146,15 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
|
|||||||
.antMatchers("/swagger-resources/**").anonymous()
|
.antMatchers("/swagger-resources/**").anonymous()
|
||||||
.antMatchers("/webjars/**").anonymous()
|
.antMatchers("/webjars/**").anonymous()
|
||||||
.antMatchers("/*/api-docs").anonymous()
|
.antMatchers("/*/api-docs").anonymous()
|
||||||
// Spring Boot Admin Server 的安全配置 TODO 芋艿:需要抽象出去
|
|
||||||
.antMatchers(adminSeverContextPath).anonymous()
|
|
||||||
.antMatchers(adminSeverContextPath + "/**").anonymous()
|
|
||||||
// Spring Boot Actuator 的安全配置
|
// Spring Boot Actuator 的安全配置
|
||||||
.antMatchers("/actuator").anonymous()
|
.antMatchers("/actuator").anonymous()
|
||||||
.antMatchers("/actuator/**").anonymous()
|
.antMatchers("/actuator/**").anonymous()
|
||||||
// Druid 监控 TODO 芋艿:需要抽象出去
|
// Druid 监控 TODO 芋艿:等对接了 druid admin 后,在调整下。
|
||||||
.antMatchers("/druid/**").anonymous()
|
.antMatchers("/druid/**").anonymous()
|
||||||
// 短信回调 API TODO 芋艿:需要抽象出去
|
// 设置每个请求的权限 ②:每个项目的自定义规则
|
||||||
.antMatchers(api("/system/sms/callback/**")).anonymous()
|
.and().authorizeRequests(authorizeRequestsCustomizer)
|
||||||
.antMatchers(api("/user/**")).anonymous()
|
// 设置每个请求的权限 ③:兜底规则,必须认证
|
||||||
// 除上面外的所有请求全部需要鉴权认证
|
.authorizeRequests().anyRequest().authenticated();
|
||||||
.anyRequest().authenticated()
|
|
||||||
.and()
|
|
||||||
.headers().frameOptions().disable();
|
|
||||||
httpSecurity.logout().logoutUrl(api("/logout")).logoutSuccessHandler(logoutSuccessHandler);
|
|
||||||
// 添加 JWT Filter
|
// 添加 JWT Filter
|
||||||
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package cn.iocoder.yudao.framework.security.core.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 声明用户需要登陆
|
||||||
|
*
|
||||||
|
* 为什么不使用 {@link org.springframework.security.access.prepost.PreAuthorize} 注解,原因是不通过时,抛出的是认证不通过,而不是未登陆
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Inherited
|
||||||
|
@Documented
|
||||||
|
public @interface PreAuthenticated {
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package cn.iocoder.yudao.framework.security.core.aop;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
|
||||||
|
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.UNAUTHORIZED;
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
|
||||||
|
@Aspect
|
||||||
|
@Slf4j
|
||||||
|
public class PreAuthenticatedAspect {
|
||||||
|
|
||||||
|
@Around("@annotation(preAuthenticated)")
|
||||||
|
public Object around(ProceedingJoinPoint joinPoint, PreAuthenticated preAuthenticated) throws Throwable {
|
||||||
|
if (SecurityFrameworkUtils.getLoginUser() == null) {
|
||||||
|
throw exception(UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
return joinPoint.proceed();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package cn.iocoder.yudao.userserver.framework.security;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class SecurityConfiguration {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private WebProperties webProperties;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer() {
|
||||||
|
return registry -> {
|
||||||
|
registry.antMatchers(api("/**")).anonymous(); // 默认 API 都是用户可访问
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private String api(String url) {
|
||||||
|
return webProperties.getApiPrefix() + url;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,9 @@
|
|||||||
package cn.iocoder.yudao.userserver.modules.infra.controller;
|
package cn.iocoder.yudao.userserver.modules.infra.controller;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.security.access.annotation.Secured;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@ -15,4 +18,11 @@ public class HelloController {
|
|||||||
public String hello(String hello) {
|
public String hello(String hello) {
|
||||||
return "echo + " + hello;
|
return "echo + " + hello;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/user/info")
|
||||||
|
@PreAuthenticated
|
||||||
|
public String xx() {
|
||||||
|
return "none";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user