@@ -0,0 +1,29 @@ | |||
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; | |||
/** | |||
* <p> | |||
* 自定义配置 | |||
* </p> | |||
* | |||
* @package: com.xkcoding.rbac.security.config | |||
* @description: 自定义配置 | |||
* @author: yangkai.shen | |||
* @date: Created in 2018-12-13 10:56 | |||
* @copyright: Copyright (c) 2018 | |||
* @version: V1.0 | |||
* @modified: yangkai.shen | |||
*/ | |||
@ConfigurationProperties(prefix = "custom.config") | |||
@Data | |||
public class CustomConfig { | |||
/** | |||
* 不需要拦截的地址 | |||
*/ | |||
private List<String> ignores = Lists.newArrayList(); | |||
} |
@@ -1,5 +1,6 @@ | |||
package com.xkcoding.rbac.security.config; | |||
import cn.hutool.core.collection.CollUtil; | |||
import cn.hutool.core.util.StrUtil; | |||
import com.xkcoding.rbac.security.common.Status; | |||
import com.xkcoding.rbac.security.exception.SecurityException; | |||
@@ -12,8 +13,8 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio | |||
import org.springframework.security.core.context.SecurityContextHolder; | |||
import org.springframework.security.core.userdetails.UserDetails; | |||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; | |||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; | |||
import org.springframework.stereotype.Component; | |||
import org.springframework.util.AntPathMatcher; | |||
import org.springframework.web.filter.OncePerRequestFilter; | |||
import javax.servlet.FilterChain; | |||
@@ -44,32 +45,41 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { | |||
@Autowired | |||
private JwtUtil jwtUtil; | |||
@Autowired | |||
private CustomConfig customConfig; | |||
@Override | |||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { | |||
AntPathMatcher antPathMatcher = new AntPathMatcher(); | |||
if (antPathMatcher.match("/**/api/auth/**", request.getRequestURI())) { | |||
filterChain.doFilter(request, response); | |||
} else { | |||
String jwt = jwtUtil.getJwtFromRequest(request); | |||
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 (StrUtil.isNotBlank(jwt)) { | |||
try { | |||
String username = jwtUtil.getUsernameFromJWT(jwt); | |||
String jwt = jwtUtil.getJwtFromRequest(request); | |||
UserDetails userDetails = customUserDetailsService.loadUserByUsername(username); | |||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); | |||
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); | |||
if (StrUtil.isNotBlank(jwt)) { | |||
try { | |||
String username = jwtUtil.getUsernameFromJWT(jwt); | |||
SecurityContextHolder.getContext() | |||
.setAuthentication(authentication); | |||
filterChain.doFilter(request, response); | |||
} catch (SecurityException e) { | |||
ResponseUtil.renderJson(response, e); | |||
} | |||
} else { | |||
ResponseUtil.renderJson(response, Status.UNAUTHORIZED, null); | |||
UserDetails userDetails = customUserDetailsService.loadUserByUsername(username); | |||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); | |||
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); | |||
SecurityContextHolder.getContext() | |||
.setAuthentication(authentication); | |||
filterChain.doFilter(request, response); | |||
} catch (SecurityException e) { | |||
ResponseUtil.renderJson(response, e); | |||
} | |||
} else { | |||
ResponseUtil.renderJson(response, Status.UNAUTHORIZED, null); | |||
} | |||
} | |||
} |
@@ -1,20 +1,22 @@ | |||
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.security.authentication.AuthenticationManager; | |||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; | |||
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.configuration.EnableWebSecurity; | |||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; | |||
import org.springframework.security.config.http.SessionCreationPolicy; | |||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | |||
import org.springframework.security.web.access.AccessDeniedHandler; | |||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | |||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; | |||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; | |||
/** | |||
* <p> | |||
@@ -31,7 +33,11 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher; | |||
*/ | |||
@Configuration | |||
@EnableWebSecurity | |||
@EnableConfigurationProperties(CustomConfig.class) | |||
public class SecurityConfig extends WebSecurityConfigurerAdapter { | |||
@Autowired | |||
private CustomConfig customConfig; | |||
@Autowired | |||
private AccessDeniedHandler accessDeniedHandler; | |||
@@ -76,8 +82,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { | |||
// 认证请求 | |||
.authorizeRequests() | |||
// 放行 /api/auth/** 的所有请求,参见 AuthController | |||
.antMatchers("/**/api/auth/**") | |||
.permitAll() | |||
//.antMatchers("/api/auth/**") | |||
//.permitAll() | |||
.anyRequest() | |||
.authenticated() | |||
// RBAC 动态 url 认证 | |||
@@ -86,7 +92,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { | |||
// 登出行为由自己实现,参考 AuthController#logout | |||
.and() | |||
.logout().disable() | |||
.logout() | |||
.disable() | |||
// Session 管理 | |||
.sessionManagement() | |||
@@ -101,4 +108,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { | |||
// 添加自定义 JWT 过滤器 | |||
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); | |||
} | |||
@Override | |||
public void configure(WebSecurity web) throws Exception { | |||
if (CollUtil.isNotEmpty(customConfig.getIgnores())) { | |||
web.ignoring() | |||
.antMatchers(ArrayUtil.toArray(customConfig.getIgnores(), String.class)); | |||
} | |||
} | |||
} |
@@ -47,3 +47,8 @@ jwt: | |||
logging: | |||
level: | |||
com.xkcoding.rbac.security: debug | |||
custom: | |||
config: | |||
ignores: | |||
- "/api/auth/login" | |||
- "/api/auth/logout" |