Skip to content

Commit 9e77d1c

Browse files
committed
feat: 抽离 security 认证相关配置到 framework 服务
1 parent 90a2290 commit 9e77d1c

46 files changed

Lines changed: 326 additions & 224 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

common/plugin/log/src/main/java/com/github/cadecode/uniboot/common/plugin/log/aspect/ApiLoggerAspect.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public void handleLogger(ProceedingJoinPoint point, ApiLogger apiLogger, Object
101101
resultStr = JacksonUtil.toJson(result);
102102
} catch (Exception e) {
103103
resultStr = ExceptionUtil.stacktraceToString(e);
104-
log.warn("API log [{}]: request result to json fail", apiLogger.type().getType(), e);
104+
log.error("API log [{}]: request result to json fail", apiLogger.type().getType(), e);
105105
}
106106
}
107107
BaseLogInfo baseLogInfo = BaseLogInfo.builder().apiLogger(apiLogger).request(attributes.getRequest())
@@ -113,10 +113,10 @@ public void handleLogger(ProceedingJoinPoint point, ApiLogger apiLogger, Object
113113
try {
114114
apiLogHandler.save(apiLogger, logObj);
115115
} catch (Exception e) {
116-
log.warn("API log [{}]: save async fail", apiLogger.type().getType(), e);
116+
log.error("API log [{}]: save async fail", apiLogger.type().getType(), e);
117117
}
118118
} catch (Exception e) {
119-
log.warn("API log [{}]: handle logger fail", apiLogger.type().getType(), e);
119+
log.error("API log [{}]: handle logger fail", apiLogger.type().getType(), e);
120120
}
121121
}
122122

common/plugin/log/src/main/java/com/github/cadecode/uniboot/common/plugin/log/handler/AbstractApiLogHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public static Map<String, Object> getRequestParams(JoinPoint joinPoint, ApiLogge
4141
return Collections.emptyMap();
4242
}
4343
if (names.length != args.length) {
44-
log.warn("API log [{}]: method [{}] param and the pass value do not match", apiLogger.type().getType(), methodSignature.getName());
44+
log.error("API log [{}]: method [{}] param and the pass value do not match", apiLogger.type().getType(), methodSignature.getName());
4545
return Collections.emptyMap();
4646
}
4747
Map<String, Object> map = new HashMap<>();

example/example_svc/src/main/resources/bootstrap.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@ logging:
22
file:
33
path: /log/uni_boot_admin/example
44

5-
server:
6-
servlet:
7-
context-path: /example
8-
95
spring:
106
application:
117
name: uni-boot-example

framework/framework_api/src/main/java/com/github/cadecode/uniboot/framework/api/config/SecurityConfig.java

Lines changed: 46 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,25 @@
55
import com.github.cadecode.uniboot.framework.api.config.SecurityConfig.SecurityProperties;
66
import com.github.cadecode.uniboot.framework.api.enums.AuthModelEnum;
77
import com.github.cadecode.uniboot.framework.api.security.filter.TokenAuthFilter;
8-
import com.github.cadecode.uniboot.framework.api.security.handler.*;
8+
import com.github.cadecode.uniboot.framework.api.security.handler.NoAuthenticationHandler;
9+
import com.github.cadecode.uniboot.framework.api.security.handler.NoAuthorityHandler;
910
import com.github.cadecode.uniboot.framework.api.security.voter.DataBaseRoleVoter;
1011
import lombok.Data;
1112
import lombok.RequiredArgsConstructor;
1213
import lombok.extern.slf4j.Slf4j;
14+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
1315
import org.springframework.boot.context.properties.ConfigurationProperties;
1416
import org.springframework.boot.context.properties.EnableConfigurationProperties;
15-
import org.springframework.context.annotation.Bean;
1617
import org.springframework.context.annotation.Configuration;
1718
import org.springframework.http.HttpMethod;
1819
import org.springframework.security.access.vote.UnanimousBased;
19-
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
2020
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
2121
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
2222
import org.springframework.security.config.annotation.web.builders.WebSecurity;
2323
import org.springframework.security.config.annotation.web.builders.WebSecurity.IgnoredRequestConfigurer;
2424
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
2525
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
2626
import org.springframework.security.config.http.SessionCreationPolicy;
27-
import org.springframework.security.core.userdetails.UserDetailsService;
28-
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
29-
import org.springframework.security.crypto.password.PasswordEncoder;
3027
import org.springframework.security.web.access.expression.WebExpressionVoter;
3128
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
3229

@@ -40,29 +37,13 @@
4037
* @date 2022/5/27
4138
*/
4239
@Slf4j
43-
@Data
4440
@RequiredArgsConstructor
4541
@EnableWebSecurity
4642
@EnableGlobalMethodSecurity(prePostEnabled = true)
4743
@EnableConfigurationProperties(SecurityProperties.class)
44+
@ConditionalOnMissingBean(SecurityConfig.class)
4845
@Configuration
49-
public class SecurityConfig {
50-
51-
/**
52-
* 登录路径
53-
*/
54-
public static final String LOGIN_URL = "/login";
55-
56-
/**
57-
* 登录参数
58-
*/
59-
public static final String USERNAME_PARAMETER = "username";
60-
public static final String PASSWORD_PARAMETER = "password";
61-
62-
/**
63-
* 注销路径
64-
*/
65-
public static final String LOGOUT_URL = "/logout";
46+
public class SecurityConfig extends WebSecurityConfigurerAdapter {
6647

6748
/**
6849
* 配置项
@@ -72,11 +53,8 @@ public class SecurityConfig {
7253
/**
7354
* 注入各种处理器
7455
*/
75-
private final LoginSuccessHandler loginSuccessHandler;
76-
private final LoginFailureHandler loginFailureHandler;
7756
private final NoAuthenticationHandler noAuthenticationHandler;
7857
private final NoAuthorityHandler noAuthorityHandler;
79-
private final SignOutSuccessHandler signOutSuccessHandler;
8058

8159
/**
8260
* 注入 Token 过滤器
@@ -88,88 +66,50 @@ public class SecurityConfig {
8866
*/
8967
private final DataBaseRoleVoter dataBaseRoleVoter;
9068

91-
/**
92-
* 注入 UserDetailsService
93-
*/
94-
private final UserDetailsService userDetailsService;
95-
96-
/**
97-
* 密码加密器
98-
*/
99-
@Bean
100-
public PasswordEncoder passwordEncoder() {
101-
return new BCryptPasswordEncoder();
69+
@Override
70+
protected void configure(HttpSecurity http) throws Exception {
71+
// 关闭 csrf
72+
http.csrf().disable();
73+
// 关闭 session 管理
74+
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
75+
// 配置鉴权规则
76+
http.authorizeRequests()
77+
// 尝试请求直接通过
78+
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
79+
.anyRequest().authenticated();
80+
// 配置异常处理
81+
http.exceptionHandling()
82+
// 配置未登录处理器
83+
.authenticationEntryPoint(noAuthenticationHandler)
84+
// 配置无权限处理器
85+
.accessDeniedHandler(noAuthorityHandler);
86+
// 自定义的 accessDecisionManager
87+
http.authorizeRequests()
88+
.accessDecisionManager(new UnanimousBased(
89+
Arrays.asList(new WebExpressionVoter(), dataBaseRoleVoter)));
90+
// 配置 Token 校验过滤器
91+
http.addFilterBefore(tokenAuthFilter, UsernamePasswordAuthenticationFilter.class);
92+
log.info("Config Security over,AuthModel:{}", properties.getAuthModel());
10293
}
10394

104-
/**
105-
* Security 配置
106-
*/
107-
@Bean
108-
public WebSecurityConfigurerAdapter webSecurityConfigurer(PasswordEncoder passwordEncoder) {
109-
return new WebSecurityConfigurerAdapter() {
110-
111-
@Override
112-
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
113-
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
114-
}
115-
116-
@Override
117-
protected void configure(HttpSecurity http) throws Exception {
118-
// 关闭 csrf
119-
http.csrf().disable();
120-
// 关闭 session 管理
121-
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
122-
// 配置鉴权规则
123-
http.authorizeRequests()
124-
// 尝试请求直接通过
125-
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
126-
.anyRequest().authenticated();
127-
// 配置注销处理器
128-
http.logout().permitAll()
129-
.logoutUrl(LOGOUT_URL)
130-
.logoutSuccessHandler(signOutSuccessHandler);
131-
// 配置异常处理
132-
http.exceptionHandling()
133-
// 配置未登录处理器
134-
.authenticationEntryPoint(noAuthenticationHandler)
135-
// 配置无权限处理器
136-
.accessDeniedHandler(noAuthorityHandler);
137-
// 自定义的 accessDecisionManager
138-
http.authorizeRequests()
139-
.accessDecisionManager(new UnanimousBased(
140-
Arrays.asList(new WebExpressionVoter(), dataBaseRoleVoter)));
141-
// 配置登录处理器
142-
http.formLogin().permitAll()
143-
.loginProcessingUrl(LOGIN_URL)
144-
.usernameParameter(USERNAME_PARAMETER)
145-
.passwordParameter(PASSWORD_PARAMETER)
146-
.successHandler(loginSuccessHandler)
147-
.failureHandler(loginFailureHandler);
148-
// 配置 Token 校验过滤器
149-
http.addFilterBefore(tokenAuthFilter, UsernamePasswordAuthenticationFilter.class);
150-
log.info("Config Security over,AuthModel:{}", properties.getAuthModel());
151-
}
152-
153-
@Override
154-
public void configure(WebSecurity web) {
155-
// 忽略配置器
156-
IgnoredRequestConfigurer ignoring = web.ignoring();
157-
// 放行 swagger knife 文档
158-
ignoring.antMatchers("/doc.html", "/webjars/**", "/swagger-resources/**", "/v2/api-docs/**");
159-
// 放行其他框架
160-
ignoring.antMatchers("/error", "/druid/**", "/actuator/**");
161-
// 设置忽略的路径
162-
List<String> ignoreUrls = properties.getIgnoreUrls();
163-
if (CollUtil.isNotEmpty(ignoreUrls)) {
164-
log.info("Config Security ignore urls:{}", ignoreUrls);
165-
ignoring.antMatchers(ArrayUtil.toArray(ignoreUrls, String.class));
166-
}
167-
}
168-
};
95+
@Override
96+
public void configure(WebSecurity web) {
97+
// 忽略配置器
98+
IgnoredRequestConfigurer ignoring = web.ignoring();
99+
// 放行 swagger knife 文档
100+
ignoring.antMatchers("/doc.html", "/webjars/**", "/swagger-resources/**", "/v2/api-docs/**");
101+
// 放行其他框架
102+
ignoring.antMatchers("/error", "/druid/**", "/actuator/**");
103+
// 设置忽略的路径
104+
List<String> ignoreUrls = properties.getIgnoreUrls();
105+
if (CollUtil.isNotEmpty(ignoreUrls)) {
106+
log.info("Config Security ignore urls:{}", ignoreUrls);
107+
ignoring.antMatchers(ArrayUtil.toArray(ignoreUrls, String.class));
108+
}
169109
}
170110

171111
/**
172-
* Security 配置
112+
* Security 配置项
173113
*/
174114
@Data
175115
@ConfigurationProperties("uni-boot.security")
@@ -188,12 +128,11 @@ public static class SecurityProperties {
188128
/**
189129
* JWT Token 配置
190130
*/
191-
private TokenConfig token;
192-
131+
private TokenConfig tokenConfig;
193132
}
194133

195134
/**
196-
* JWT 配置类
135+
* JWT 配置项
197136
*/
198137
@Data
199138
public static class TokenConfig {
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.github.cadecode.uniboot.framework.api.feign;
2+
3+
import com.github.cadecode.uniboot.framework.api.bean.vo.SysApiVo.SysApiRolesVo;
4+
import com.github.cadecode.uniboot.framework.api.consts.KeyPrefix;
5+
import org.springframework.cache.annotation.Cacheable;
6+
import org.springframework.cloud.openfeign.FeignClient;
7+
import org.springframework.web.bind.annotation.PostMapping;
8+
9+
import java.util.List;
10+
11+
/**
12+
* SysApi feign client
13+
*
14+
* @author Cade Li
15+
* @since 2023/7/28
16+
*/
17+
@FeignClient(contextId = "SysApiClient", name = "uni-boot-framework")
18+
public interface SysApiClient {
19+
20+
@Cacheable(cacheNames = KeyPrefix.API_ROLES, key = "'all'")
21+
@PostMapping("system/api/list_roles_vo")
22+
List<SysApiRolesVo> listRolesVo();
23+
24+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.github.cadecode.uniboot.framework.api.feign;
2+
3+
import com.github.cadecode.uniboot.framework.api.bean.po.SysLog;
4+
import org.springframework.cloud.openfeign.FeignClient;
5+
import org.springframework.web.bind.annotation.PostMapping;
6+
import org.springframework.web.bind.annotation.RequestBody;
7+
8+
import javax.validation.constraints.NotEmpty;
9+
import java.util.List;
10+
11+
/**
12+
* SysLog feign client
13+
*
14+
* @author Cade Li
15+
* @since 2023/7/28
16+
*/
17+
@FeignClient(contextId = "SysLogClient", name = "uni-boot-framework")
18+
public interface SysLogClient {
19+
20+
@PostMapping("system/log/save")
21+
boolean save(@RequestBody @NotEmpty List<SysLog> poList);
22+
23+
}

framework/framework_api/src/main/java/com/github/cadecode/uniboot/framework/api/plugin/ApiLogHandler.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import com.github.cadecode.uniboot.framework.api.bean.dto.SysLogDto.SysLogInfoDto;
1313
import com.github.cadecode.uniboot.framework.api.bean.po.SysLog;
1414
import com.github.cadecode.uniboot.framework.api.convert.SysLogConvert;
15-
import com.github.cadecode.uniboot.framework.api.service.SysLogService;
15+
import com.github.cadecode.uniboot.framework.api.feign.SysLogClient;
1616
import com.github.cadecode.uniboot.framework.api.util.SecurityUtil;
1717
import io.swagger.annotations.ApiOperation;
1818
import lombok.RequiredArgsConstructor;
@@ -22,6 +22,8 @@
2222
import org.springframework.scheduling.annotation.Async;
2323
import org.springframework.stereotype.Component;
2424

25+
import java.util.Collections;
26+
2527
/**
2628
* Api Log 处理器实现
2729
*
@@ -33,7 +35,7 @@
3335
@Component
3436
public class ApiLogHandler extends AbstractApiLogHandler {
3537

36-
private final SysLogService sysLogService;
38+
private final SysLogClient sysLogClient;
3739

3840
/**
3941
* 构造 LogInfo
@@ -49,7 +51,7 @@ public SysLogInfoDto generateLog(ProceedingJoinPoint point, BaseLogInfo baseLogI
4951
paramsJson = JacksonUtil.toJson(getRequestParams(point, apiLogger));
5052
} catch (Exception e) {
5153
paramsJson = ExceptionUtil.stacktraceToString(e);
52-
log.warn("API log [{}]: request params to json fail", apiLogger.type().getType(), e);
54+
log.error("API log [{}]: request params to json fail", apiLogger.type().getType(), e);
5355
}
5456
// 获取描述
5557
String description = apiLogger.description();
@@ -94,6 +96,10 @@ public void save(ApiLogger apiLogger, Object o) {
9496
if (!apiLogger.saveResult()) {
9597
po.setResult(null);
9698
}
97-
sysLogService.save(po);
99+
try {
100+
sysLogClient.save(Collections.singletonList(po));
101+
} catch (Exception e) {
102+
log.error("API log [{}]: save fail", apiLogger.type().getType(), e);
103+
}
98104
}
99105
}

framework/framework_api/src/main/java/com/github/cadecode/uniboot/framework/api/security/voter/DataBaseRoleVoter.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package com.github.cadecode.uniboot.framework.api.security.voter;
22

33
import cn.hutool.core.util.ObjectUtil;
4-
import com.github.cadecode.uniboot.framework.api.bean.dto.SysUserDto;
4+
import com.github.cadecode.uniboot.framework.api.bean.dto.SysUserDto.SysUserDetailsDto;
55
import com.github.cadecode.uniboot.framework.api.bean.vo.SysApiVo.SysApiRolesVo;
6-
import com.github.cadecode.uniboot.framework.api.service.SysApiService;
6+
import com.github.cadecode.uniboot.framework.api.feign.SysApiClient;
77
import com.github.cadecode.uniboot.framework.api.util.SecurityUtil;
88
import lombok.RequiredArgsConstructor;
99
import org.springframework.security.access.ConfigAttribute;
@@ -31,7 +31,7 @@ public class DataBaseRoleVoter extends RoleVoter {
3131
// ant 匹配器
3232
private final AntPathMatcher antPathMatcher = new AntPathMatcher();
3333

34-
private final SysApiService sysApiService;
34+
private final SysApiClient sysApiClient;
3535

3636
@Override
3737
public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
@@ -42,9 +42,9 @@ public int vote(Authentication authentication, Object object, Collection<ConfigA
4242
FilterInvocation fi = (FilterInvocation) object;
4343
String requestUrl = fi.getRequest().getRequestURI();
4444
// 获取 api role 的关系列表
45-
List<SysApiRolesVo> sysApiRolesVos = sysApiService.listRolesVo();
45+
List<SysApiRolesVo> sysApiRolesVos = sysApiClient.listRolesVo();
4646
// 获取用户角色
47-
SysUserDto.SysUserDetailsDto sysUserDetailsDto = SecurityUtil.getUserDetails(authentication);
47+
SysUserDetailsDto sysUserDetailsDto = SecurityUtil.getUserDetails(authentication);
4848
List<String> roles = sysUserDetailsDto.getRoles();
4949
// 获取与 url 相同的配置,不存在与 url 相同配置则使用 spring mvc ant 风格匹配
5050
SysApiRolesVo sysApiRolesVo = sysApiRolesVos.stream()

0 commit comments

Comments
 (0)