diff --git a/eladmin-system/pom.xml b/eladmin-system/pom.xml
index fbc1e007..09b9bcfc 100644
--- a/eladmin-system/pom.xml
+++ b/eladmin-system/pom.xml
@@ -35,6 +35,12 @@
2.2
+
+ org.springframework.boot
+ spring-boot-devtools
+ true
+
+
io.jsonwebtoken
diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/AnonymousAccessController.java b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/AnonymousAccessController.java
new file mode 100644
index 00000000..1b304dc8
--- /dev/null
+++ b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/AnonymousAccessController.java
@@ -0,0 +1,38 @@
+package me.zhengjie.modules.monitor.rest;
+
+import me.zhengjie.modules.security.annotation.AnonymousAccess;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * 匿名访问测试类
+ */
+@RestController
+@RequestMapping("api")
+public class AnonymousAccessController {
+ private static final AtomicInteger ATOMIC_INTEGER = new AtomicInteger();
+
+
+ @GetMapping("/anonymousAccess1")
+ @AnonymousAccess
+ public int testAnonymousAccess1() {
+ return ATOMIC_INTEGER.incrementAndGet();
+ }
+
+ @GetMapping("/anonymousAccess2")
+ @AnonymousAccess
+ @PreAuthorize("hasAnyRole('ROLE_ANONYMOUS')")
+ public int testAnonymousAccess2() {
+ return ATOMIC_INTEGER.incrementAndGet();
+ }
+
+ @GetMapping("/anonymousAccess3")
+ @PreAuthorize("hasAnyRole('ROLE_ANONYMOUS')")
+ public int testAnonymousAccess3() {
+ return ATOMIC_INTEGER.incrementAndGet();
+ }
+}
diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/LimitController.java b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/LimitController.java
index 3a742cac..1802d3a5 100644
--- a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/LimitController.java
+++ b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/LimitController.java
@@ -1,6 +1,7 @@
package me.zhengjie.modules.monitor.rest;
import me.zhengjie.annotation.Limit;
+import me.zhengjie.modules.security.annotation.AnonymousAccess;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -21,6 +22,7 @@ public class LimitController {
*/
@Limit(key = "test", period = 60, count = 10, name = "testLimit", prefix = "limit")
@GetMapping("/limit")
+ @AnonymousAccess
public int testLimit() {
return ATOMIC_INTEGER.incrementAndGet();
}
diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/annotation/AnonymousAccess.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/annotation/AnonymousAccess.java
new file mode 100644
index 00000000..661792cf
--- /dev/null
+++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/annotation/AnonymousAccess.java
@@ -0,0 +1,18 @@
+package me.zhengjie.modules.security.annotation;
+
+import me.zhengjie.aspect.LimitType;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author jacky
+ * 用于标记匿名访问方法
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AnonymousAccess {
+
+}
diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SecurityConfig.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SecurityConfig.java
index d10bd218..4aa256cb 100644
--- a/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SecurityConfig.java
+++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SecurityConfig.java
@@ -1,13 +1,16 @@
package me.zhengjie.modules.security.config;
+import me.zhengjie.modules.security.annotation.AnonymousAccess;
import me.zhengjie.modules.security.security.JwtAuthenticationEntryPoint;
import me.zhengjie.modules.security.security.JwtAuthorizationTokenFilter;
import me.zhengjie.modules.security.service.JwtUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
+import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
@@ -19,6 +22,13 @@ import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
@Configuration
@EnableWebSecurity
@@ -30,6 +40,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtUserDetailsService jwtUserDetailsService;
+ @Autowired
+ private ApplicationContext applicationContext;
/**
* 自定义基于JWT的安全过滤器
@@ -50,6 +62,17 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
.passwordEncoder(passwordEncoderBean());
}
+// @Bean
+// public AnonymousAuthenticationFilter anonymousAuthenticationFilter() {
+// AnonymousAuthenticationFilter authenticationFilter = new AnonymousAuthenticationFilter("anonymous");
+// return authenticationFilter;
+// }
+//
+// @Bean
+// public AnonymousAuthenticationProvider anonymousAuthenticationProvider() {
+// return new AnonymousAuthenticationProvider("anonymous");
+// }
+
@Bean
GrantedAuthorityDefaults grantedAuthorityDefaults() {
// Remove the ROLE_ prefix
@@ -69,7 +92,19 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
-
+ Map handlerMethodMap = applicationContext.getBean(RequestMappingHandlerMapping.class).getHandlerMethods();
+ Set anonymousUrls = new HashSet<>();
+ for (Map.Entry infoEntry : handlerMethodMap.entrySet()) {
+ HandlerMethod handlerMethod = infoEntry.getValue();
+ AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class);
+ PreAuthorize preAuthorize = handlerMethod.getMethodAnnotation(PreAuthorize.class);
+ // PreAuthorize("hasAnyRole('ROLE_ANONYMOUS')") 和 AnonymousAccess
+ if (null != preAuthorize && preAuthorize.value().contains("ROLE_ANONYMOUS")) {
+ anonymousUrls.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
+ } else if (null != anonymousAccess && null == preAuthorize) {
+ anonymousUrls.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
+ }
+ }
httpSecurity
// 禁用 CSRF
@@ -91,7 +126,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
"/**/*.js"
).anonymous()
- .antMatchers( HttpMethod.POST,"/auth/"+loginPath).anonymous()
+ .antMatchers(HttpMethod.POST, "/auth/" + loginPath).anonymous()
.antMatchers("/auth/vCode").anonymous()
// 支付宝回调
.antMatchers("/api/aliPay/return").anonymous()
@@ -114,12 +149,14 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
.antMatchers(HttpMethod.OPTIONS, "/**").anonymous()
.antMatchers("/druid/**").anonymous()
+ // 自定义匿名访问所有url放行
+ .antMatchers(anonymousUrls.toArray(new String[0])).anonymous()
// 所有请求都需要认证
.anyRequest().authenticated()
+
// 防止iframe 造成跨域
.and().headers().frameOptions().disable();
- httpSecurity
- .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
+ httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
}
}
diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthenticationEntryPoint.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthenticationEntryPoint.java
index f1504671..9dfbb938 100644
--- a/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthenticationEntryPoint.java
+++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthenticationEntryPoint.java
@@ -21,6 +21,6 @@ public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Se
/**
* 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应
*/
- response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException==null?"Unauthorized":authException.getMessage());
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException == null ? "Unauthorized" : authException.getMessage());
}
}
diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthorizationTokenFilter.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthorizationTokenFilter.java
index 1693bcc1..8ca24fdf 100644
--- a/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthorizationTokenFilter.java
+++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthorizationTokenFilter.java
@@ -5,7 +5,9 @@ import lombok.extern.slf4j.Slf4j;
import me.zhengjie.modules.security.utils.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
@@ -61,6 +63,10 @@ public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
+ } else {
+// AnonymousAuthenticationToken anonymousAuthenticationToken = new AnonymousAuthenticationToken("anonymous", "anonymousUser", AuthorityUtils.createAuthorityList(new String[]{"ROLE_ANONYMOUS"}));
+// anonymousAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+// SecurityContextHolder.getContext().setAuthentication(anonymousAuthenticationToken);
}
chain.doFilter(request, response);
}