diff --git a/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/CustomConfig.java b/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/CustomConfig.java index 3a691232..32f3cf7 100644 --- a/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/CustomConfig.java +++ b/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/CustomConfig.java @@ -1,11 +1,8 @@ package com.xkcoding.rbac.security.config; -import com.google.common.collect.Lists; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; -import java.util.List; - /** *

* 自定义配置 @@ -25,5 +22,5 @@ public class CustomConfig { /** * 不需要拦截的地址 */ - private List ignores = Lists.newArrayList(); + private IgnoreConfig ignores; } diff --git a/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/IgnoreConfig.java b/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/IgnoreConfig.java new file mode 100644 index 0000000..2bbc40f --- /dev/null +++ b/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/IgnoreConfig.java @@ -0,0 +1,67 @@ +package com.xkcoding.rbac.security.config; + +import com.google.common.collect.Lists; +import lombok.Data; + +import java.util.List; + +/** + *

+ * 忽略配置 + *

+ * + * @package: com.xkcoding.rbac.security.config + * @description: 忽略配置 + * @author: yangkai.shen + * @date: Created in 2018-12-17 17:37 + * @copyright: Copyright (c) 2018 + * @version: V1.0 + * @modified: yangkai.shen + */ +@Data +public class IgnoreConfig { + /** + * 需要忽略的 URL 格式,不考虑请求方法 + */ + private List pattern = Lists.newArrayList(); + + /** + * 需要忽略的 GET 请求 + */ + private List get = Lists.newArrayList(); + + /** + * 需要忽略的 POST 请求 + */ + private List post = Lists.newArrayList(); + + /** + * 需要忽略的 DELETE 请求 + */ + private List delete = Lists.newArrayList(); + + /** + * 需要忽略的 PUT 请求 + */ + private List put = Lists.newArrayList(); + + /** + * 需要忽略的 HEAD 请求 + */ + private List head = Lists.newArrayList(); + + /** + * 需要忽略的 PATCH 请求 + */ + private List patch = Lists.newArrayList(); + + /** + * 需要忽略的 OPTIONS 请求 + */ + private List options = Lists.newArrayList(); + + /** + * 需要忽略的 TRACE 请求 + */ + private List trace = Lists.newArrayList(); +} diff --git a/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/JwtAuthenticationFilter.java b/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/JwtAuthenticationFilter.java index 67f0b5c..165d230 100644 --- a/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/JwtAuthenticationFilter.java +++ b/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/JwtAuthenticationFilter.java @@ -1,7 +1,9 @@ package com.xkcoding.rbac.security.config; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import com.google.common.collect.Sets; import com.xkcoding.rbac.security.common.Status; import com.xkcoding.rbac.security.exception.SecurityException; import com.xkcoding.rbac.security.service.CustomUserDetailsService; @@ -9,6 +11,7 @@ import com.xkcoding.rbac.security.util.JwtUtil; import com.xkcoding.rbac.security.util.ResponseUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpMethod; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; @@ -22,6 +25,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.util.Set; /** *

@@ -50,14 +54,10 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - if (CollUtil.isNotEmpty(customConfig.getIgnores())) { - for (String ignore : customConfig.getIgnores()) { - AntPathRequestMatcher matcher = new AntPathRequestMatcher(ignore); - if (matcher.matches(request)) { - filterChain.doFilter(request, response); - return; - } - } + + if (checkIgnores(request)) { + filterChain.doFilter(request, response); + return; } String jwt = jwtUtil.getJwtFromRequest(request); @@ -82,4 +82,72 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { } + /** + * 请求是否不需要进行权限拦截 + * + * @param request 当前请求 + * @return true - 忽略,false - 不忽略 + */ + private boolean checkIgnores(HttpServletRequest request) { + String method = request.getMethod(); + + HttpMethod httpMethod = HttpMethod.resolve(method); + if (ObjectUtil.isNull(httpMethod)) { + httpMethod = HttpMethod.GET; + } + + Set ignores = Sets.newHashSet(); + + switch (httpMethod) { + case GET: + ignores.addAll(customConfig.getIgnores() + .getGet()); + break; + case PUT: + ignores.addAll(customConfig.getIgnores() + .getPut()); + break; + case HEAD: + ignores.addAll(customConfig.getIgnores() + .getHead()); + break; + case POST: + ignores.addAll(customConfig.getIgnores() + .getPost()); + break; + case PATCH: + ignores.addAll(customConfig.getIgnores() + .getPatch()); + break; + case TRACE: + ignores.addAll(customConfig.getIgnores() + .getTrace()); + break; + case DELETE: + ignores.addAll(customConfig.getIgnores() + .getDelete()); + break; + case OPTIONS: + ignores.addAll(customConfig.getIgnores() + .getOptions()); + break; + default: + break; + } + + ignores.addAll(customConfig.getIgnores() + .getPattern()); + + if (CollUtil.isNotEmpty(ignores)) { + for (String ignore : ignores) { + AntPathRequestMatcher matcher = new AntPathRequestMatcher(ignore, method); + if (matcher.matches(request)) { + return true; + } + } + } + + return false; + } + } diff --git a/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/SecurityConfig.java b/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/SecurityConfig.java index 0d9af81..44d91a9 100644 --- a/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/SecurityConfig.java +++ b/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/SecurityConfig.java @@ -1,12 +1,11 @@ package com.xkcoding.rbac.security.config; -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ArrayUtil; import com.xkcoding.rbac.security.service.CustomUserDetailsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -81,9 +80,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { // 认证请求 .authorizeRequests() - // 放行 /api/auth/** 的所有请求,参见 AuthController - //.antMatchers("/api/auth/**") - //.permitAll() + // 所有请求都需要登录访问 .anyRequest() .authenticated() // RBAC 动态 url 认证 @@ -109,11 +106,69 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); } + /** + * 放行所有不需要登录就可以访问的请求,参见 AuthController + * 也可以在 {@link #configure(HttpSecurity)} 中配置 + * {@code http.authorizeRequests().antMatchers("/api/auth/**").permitAll()} + */ @Override - public void configure(WebSecurity web) throws Exception { - if (CollUtil.isNotEmpty(customConfig.getIgnores())) { - web.ignoring() - .antMatchers(ArrayUtil.toArray(customConfig.getIgnores(), String.class)); - } + public void configure(WebSecurity web) { + WebSecurity and = web.ignoring() + .and(); + + // 忽略 GET + customConfig.getIgnores() + .getGet() + .forEach(url -> and.ignoring() + .antMatchers(HttpMethod.GET, url)); + + // 忽略 POST + customConfig.getIgnores() + .getPost() + .forEach(url -> and.ignoring() + .antMatchers(HttpMethod.POST, url)); + + // 忽略 DELETE + customConfig.getIgnores() + .getDelete() + .forEach(url -> and.ignoring() + .antMatchers(HttpMethod.DELETE, url)); + + // 忽略 PUT + customConfig.getIgnores() + .getPut() + .forEach(url -> and.ignoring() + .antMatchers(HttpMethod.PUT, url)); + + // 忽略 HEAD + customConfig.getIgnores() + .getHead() + .forEach(url -> and.ignoring() + .antMatchers(HttpMethod.HEAD, url)); + + // 忽略 PATCH + customConfig.getIgnores() + .getPatch() + .forEach(url -> and.ignoring() + .antMatchers(HttpMethod.PATCH, url)); + + // 忽略 OPTIONS + customConfig.getIgnores() + .getOptions() + .forEach(url -> and.ignoring() + .antMatchers(HttpMethod.OPTIONS, url)); + + // 忽略 TRACE + customConfig.getIgnores() + .getTrace() + .forEach(url -> and.ignoring() + .antMatchers(HttpMethod.TRACE, url)); + + // 按照请求格式忽略 + customConfig.getIgnores() + .getPattern() + .forEach(url -> and.ignoring() + .antMatchers(url)); + } } diff --git a/spring-boot-demo-rbac-security/src/main/resources/application.yml b/spring-boot-demo-rbac-security/src/main/resources/application.yml index 00dd077..2e7cfd3 100644 --- a/spring-boot-demo-rbac-security/src/main/resources/application.yml +++ b/spring-boot-demo-rbac-security/src/main/resources/application.yml @@ -50,5 +50,10 @@ logging: custom: config: ignores: - - "/api/auth/login" - - "/api/auth/logout" \ No newline at end of file + # 需要过滤的 post 请求 + post: + - "/api/auth/login" + - "/api/auth/logout" + # 需要过滤的请求,不限方法 + pattern: + - "/test/*" \ No newline at end of file