♻️ Refactoring code. 事件通知重构

This commit is contained in:
lbw 2022-06-02 17:31:34 +08:00
parent bb0864294d
commit cb91df9a33
26 changed files with 585 additions and 548 deletions

View File

@ -58,8 +58,7 @@ pig
├── pig-common-seata -- 分布式事务 ├── pig-common-seata -- 分布式事务
├── pig-common-security -- 安全工具类 ├── pig-common-security -- 安全工具类
├── pig-common-swagger -- 接口文档 ├── pig-common-swagger -- 接口文档
├── pig-common-feign -- feign 扩展封装 └── pig-common-feign -- feign 扩展封装
└── pig-common-test -- oauth2.0 单元测试扩展封装
├── pig-register -- Nacos Server[8848] ├── pig-register -- Nacos Server[8848]
├── pig-gateway -- Spring Cloud Gateway网关[9999] ├── pig-gateway -- Spring Cloud Gateway网关[9999]
└── pig-upms -- 通用用户权限管理模块 └── pig-upms -- 通用用户权限管理模块

View File

@ -16,7 +16,9 @@
package com.pig4cloud.pig.auth.config; package com.pig4cloud.pig.auth.config;
import com.pig4cloud.pig.auth.support.*; import com.pig4cloud.pig.auth.support.CustomeOAuth2AccessTokenGenerator;
import com.pig4cloud.pig.auth.support.handler.PigAuthenticationFailureEventHandler;
import com.pig4cloud.pig.auth.support.handler.PigAuthenticationSuccessEventHandler;
import com.pig4cloud.pig.auth.support.password.OAuth2ResourceOwnerPasswordAuthenticationConverter; import com.pig4cloud.pig.auth.support.password.OAuth2ResourceOwnerPasswordAuthenticationConverter;
import com.pig4cloud.pig.auth.support.password.OAuth2ResourceOwnerPasswordAuthenticationProvider; import com.pig4cloud.pig.auth.support.password.OAuth2ResourceOwnerPasswordAuthenticationProvider;
import com.pig4cloud.pig.auth.support.sms.OAuth2ResourceOwnerSmsAuthenticationConverter; import com.pig4cloud.pig.auth.support.sms.OAuth2ResourceOwnerSmsAuthenticationConverter;
@ -63,16 +65,23 @@ public class AuthorizationServerConfiguration {
OAuth2AuthorizationService authorizationService) throws Exception { OAuth2AuthorizationService authorizationService) throws Exception {
OAuth2AuthorizationServerConfigurer<HttpSecurity> authorizationServerConfigurer = new OAuth2AuthorizationServerConfigurer<>(); OAuth2AuthorizationServerConfigurer<HttpSecurity> authorizationServerConfigurer = new OAuth2AuthorizationServerConfigurer<>();
http.apply(authorizationServerConfigurer.tokenEndpoint( http.apply(authorizationServerConfigurer.tokenEndpoint((tokenEndpoint) -> {
(tokenEndpoint) -> tokenEndpoint.accessTokenRequestConverter(new DelegatingAuthenticationConverter( // sas 支持的 Converter
tokenEndpoint.accessTokenRequestConverter(new DelegatingAuthenticationConverter(
Arrays.asList(new OAuth2ResourceOwnerPasswordAuthenticationConverter(), Arrays.asList(new OAuth2ResourceOwnerPasswordAuthenticationConverter(),
new OAuth2ResourceOwnerSmsAuthenticationConverter(), new OAuth2ResourceOwnerSmsAuthenticationConverter(),
new OAuth2RefreshTokenAuthenticationConverter(), new OAuth2RefreshTokenAuthenticationConverter(),
new OAuth2ClientCredentialsAuthenticationConverter(), new OAuth2ClientCredentialsAuthenticationConverter(),
new OAuth2AuthorizationCodeAuthenticationConverter(), new OAuth2AuthorizationCodeAuthenticationConverter(),
new OAuth2AuthorizationCodeRequestAuthenticationConverter()))))); new OAuth2AuthorizationCodeRequestAuthenticationConverter())));
authorizationServerConfigurer.authorizationEndpoint( // 登录成功处理器
authorizationEndpoint -> authorizationEndpoint.consentPage(CUSTOM_CONSENT_PAGE_URI)); tokenEndpoint.accessTokenResponseHandler(new PigAuthenticationSuccessEventHandler());
// 登录失败处理器
tokenEndpoint.errorResponseHandler(new PigAuthenticationFailureEventHandler());
}));
authorizationServerConfigurer.authorizationEndpoint(authorizationEndpoint -> {
authorizationEndpoint.consentPage(CUSTOM_CONSENT_PAGE_URI);
});
authorizationServerConfigurer.authorizationService(authorizationService); authorizationServerConfigurer.authorizationService(authorizationService);

View File

@ -16,16 +16,14 @@
package com.pig4cloud.pig.auth.config; package com.pig4cloud.pig.auth.config;
import com.pig4cloud.pig.auth.support.handler.FormAuthenticationFailureHandler;
import com.pig4cloud.pig.auth.support.handler.SsoLogoutSuccessHandler;
import com.pig4cloud.pig.common.security.component.PigDaoAuthenticationProvider; import com.pig4cloud.pig.common.security.component.PigDaoAuthenticationProvider;
import com.pig4cloud.pig.common.security.handler.FormAuthenticationFailureHandler;
import com.pig4cloud.pig.common.security.handler.SsoLogoutSuccessHandler;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
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.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
/** /**
* 服务安全相关配置 * 服务安全相关配置
@ -51,8 +49,11 @@ public class WebSecurityConfiguration {
.csrf().disable() .csrf().disable()
// 个性化 formLogin // 个性化 formLogin
.formLogin().loginPage("/token/login").loginProcessingUrl("/token/form") .formLogin().loginPage("/token/login").loginProcessingUrl("/token/form")
.failureHandler(authenticationFailureHandler()).and().logout() // SSO登录失败处理
.logoutSuccessHandler(logoutSuccessHandler()).deleteCookies("JSESSIONID").invalidateHttpSession(true); .failureHandler(new FormAuthenticationFailureHandler()).and().logout()
// SSO登出成功处理
.logoutSuccessHandler(new SsoLogoutSuccessHandler()).deleteCookies("JSESSIONID")
.invalidateHttpSession(true);
// 处理 UsernamePasswordAuthenticationToken // 处理 UsernamePasswordAuthenticationToken
http.authenticationProvider(new PigDaoAuthenticationProvider()); http.authenticationProvider(new PigDaoAuthenticationProvider());
@ -65,22 +66,4 @@ public class WebSecurityConfiguration {
return (web) -> web.ignoring().antMatchers("/css/**", "/error"); return (web) -> web.ignoring().antMatchers("/css/**", "/error");
} }
/**
* sso 表单登录失败处理
* @return FormAuthenticationFailureHandler
*/
@Bean
public AuthenticationFailureHandler authenticationFailureHandler() {
return new FormAuthenticationFailureHandler();
}
/**
* SSO 退出逻辑处理
* @return LogoutSuccessHandler
*/
@Bean
public LogoutSuccessHandler logoutSuccessHandler() {
return new SsoLogoutSuccessHandler();
}
} }

View File

@ -21,6 +21,7 @@ import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pig.admin.api.entity.SysOauthClientDetails; import com.pig4cloud.pig.admin.api.entity.SysOauthClientDetails;
import com.pig4cloud.pig.admin.api.feign.RemoteClientDetailsService; import com.pig4cloud.pig.admin.api.feign.RemoteClientDetailsService;
import com.pig4cloud.pig.admin.api.vo.TokenVo;
import com.pig4cloud.pig.common.security.util.OAuth2EndpointUtils; import com.pig4cloud.pig.common.security.util.OAuth2EndpointUtils;
import com.pig4cloud.pig.common.security.util.OAuth2ErrorCodesExpand; import com.pig4cloud.pig.common.security.util.OAuth2ErrorCodesExpand;
import com.pig4cloud.pig.common.core.constant.CacheConstants; import com.pig4cloud.pig.common.core.constant.CacheConstants;
@ -80,7 +81,7 @@ public class PigTokenEndpoint {
private final RemoteClientDetailsService clientDetailsService; private final RemoteClientDetailsService clientDetailsService;
private final RedisTemplate redisTemplate; private final RedisTemplate<String, Object> redisTemplate;
private final CacheManager cacheManager; private final CacheManager cacheManager;
@ -192,7 +193,20 @@ public class PigTokenEndpoint {
Set<String> keys = redisTemplate.keys(key); Set<String> keys = redisTemplate.keys(key);
List<String> pages = keys.stream().skip((current - 1) * size).limit(size).collect(Collectors.toList()); List<String> pages = keys.stream().skip((current - 1) * size).limit(size).collect(Collectors.toList());
Page result = new Page(current, size); Page result = new Page(current, size);
result.setRecords(redisTemplate.opsForValue().multiGet(pages));
List<TokenVo> tokenVoList = redisTemplate.opsForValue().multiGet(pages).stream().map(obj -> {
OAuth2Authorization authorization = (OAuth2Authorization) obj;
TokenVo tokenVo = new TokenVo();
tokenVo.setClientId(authorization.getRegisteredClientId());
tokenVo.setId(authorization.getId());
tokenVo.setUsername(authorization.getPrincipalName());
OAuth2Authorization.Token<OAuth2AccessToken> accessToken = authorization.getAccessToken();
tokenVo.setAccessToken(accessToken.getToken().getTokenValue());
tokenVo.setExpiresAt(accessToken.getToken().getExpiresAt());
tokenVo.setIssuedAt(accessToken.getToken().getIssuedAt());
return tokenVo;
}).collect(Collectors.toList());
result.setRecords(tokenVoList);
result.setTotal(keys.size()); result.setTotal(keys.size());
return R.ok(result); return R.ok(result);
} }

View File

@ -88,10 +88,9 @@ public class CustomeOAuth2AccessTokenGenerator implements OAuth2TokenGenerator<O
String key = String.format("%s::%s::%s", SecurityContextHolder.getContext().getAuthentication().getPrincipal(), String key = String.format("%s::%s::%s", SecurityContextHolder.getContext().getAuthentication().getPrincipal(),
context.getPrincipal().getName(), UUID.randomUUID()); context.getPrincipal().getName(), UUID.randomUUID());
return new CustomeOAuth2AccessTokenGenerator.OAuth2AccessTokenClaims(OAuth2AccessToken.TokenType.BEARER, key,
return new CustomeOAuth2AccessTokenGenerator.OAuth2AccessTokenClaims( accessTokenClaimsSet.getIssuedAt(), accessTokenClaimsSet.getExpiresAt(), context.getAuthorizedScopes(),
OAuth2AccessToken.TokenType.BEARER, key, accessTokenClaimsSet.getIssuedAt(), accessTokenClaimsSet.getClaims());
accessTokenClaimsSet.getExpiresAt(), context.getAuthorizedScopes(), accessTokenClaimsSet.getClaims());
} }
/** /**

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.pig4cloud.pig.common.security.handler; package com.pig4cloud.pig.auth.support.handler;
import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.HttpUtil; import cn.hutool.http.HttpUtil;
@ -29,7 +29,7 @@ import javax.servlet.http.HttpServletResponse;
/** /**
* @author lengleng * @author lengleng
* @date 2019-08-20 * @date 2022-06-02
* <p> * <p>
* 表单登录失败处理逻辑 * 表单登录失败处理逻辑
*/ */

View File

@ -0,0 +1,86 @@
/*
* Copyright (c) 2020 pig4cloud Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.pig4cloud.pig.auth.support.handler;
import com.pig4cloud.pig.admin.api.entity.SysLog;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.core.util.SpringContextHolder;
import com.pig4cloud.pig.common.log.event.SysLogEvent;
import com.pig4cloud.pig.common.log.util.LogTypeEnum;
import com.pig4cloud.pig.common.log.util.SysLogUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author lengleng
* @date 2022-06-02
*/
@Slf4j
public class PigAuthenticationFailureEventHandler implements AuthenticationFailureHandler {
private final MappingJackson2HttpMessageConverter errorHttpResponseConverter = new MappingJackson2HttpMessageConverter();
/**
* Called when an authentication attempt fails.
* @param request the request during which the authentication attempt occurred.
* @param response the response.
* @param exception the exception which was thrown to reject the authentication
* request.
*/
@Override
@SneakyThrows
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) {
String username = request.getParameter("username");
log.info("用户:{} 登录失败,异常:{}", username, exception.getLocalizedMessage());
SysLog logVo = SysLogUtils.getSysLog();
logVo.setTitle("登录失败");
logVo.setType(LogTypeEnum.ERROR.getType());
logVo.setException(exception.getLocalizedMessage());
// 发送异步日志事件
Long startTime = System.currentTimeMillis();
Long endTime = System.currentTimeMillis();
logVo.setTime(endTime - startTime);
logVo.setCreateBy(username);
logVo.setUpdateBy(username);
SpringContextHolder.publishEvent(new SysLogEvent(logVo));
// 写出错误信息
sendErrorResponse(request, response, exception);
}
private void sendErrorResponse(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException {
OAuth2Error error = ((OAuth2AuthenticationException) exception).getError();
ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
httpResponse.setStatusCode(HttpStatus.BAD_REQUEST);
this.errorHttpResponseConverter.write(R.failed(error.getDescription()), MediaType.APPLICATION_JSON,
httpResponse);
}
}

View File

@ -0,0 +1,104 @@
/*
* Copyright (c) 2020 pig4cloud Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.pig4cloud.pig.auth.support.handler;
import com.pig4cloud.pig.admin.api.entity.SysLog;
import com.pig4cloud.pig.common.core.util.SpringContextHolder;
import com.pig4cloud.pig.common.log.event.SysLogEvent;
import com.pig4cloud.pig.common.log.util.SysLogUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AccessTokenAuthenticationToken;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.util.CollectionUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.temporal.ChronoUnit;
import java.util.Map;
/**
* @author lengleng
* @date 2022-06-02
*/
@Slf4j
public class PigAuthenticationSuccessEventHandler implements AuthenticationSuccessHandler {
private final HttpMessageConverter<OAuth2AccessTokenResponse> accessTokenHttpResponseConverter = new OAuth2AccessTokenResponseHttpMessageConverter();
/**
* Called when a user has been successfully authenticated.
* @param request the request which caused the successful authentication
* @param response the response
* @param authentication the <tt>Authentication</tt> object which was created during
* the authentication process.
*/
@SneakyThrows
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) {
log.info("用户:{} 登录成功", authentication.getPrincipal());
SecurityContextHolder.getContext().setAuthentication(authentication);
SysLog logVo = SysLogUtils.getSysLog();
logVo.setTitle("登录成功");
// 发送异步日志事件
Long startTime = System.currentTimeMillis();
Long endTime = System.currentTimeMillis();
logVo.setTime(endTime - startTime);
logVo.setCreateBy(authentication.getName());
logVo.setUpdateBy(authentication.getName());
SpringContextHolder.publishEvent(new SysLogEvent(logVo));
// 输出token
sendAccessTokenResponse(request, response, authentication);
}
private void sendAccessTokenResponse(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException {
OAuth2AccessTokenAuthenticationToken accessTokenAuthentication = (OAuth2AccessTokenAuthenticationToken) authentication;
OAuth2AccessToken accessToken = accessTokenAuthentication.getAccessToken();
OAuth2RefreshToken refreshToken = accessTokenAuthentication.getRefreshToken();
Map<String, Object> additionalParameters = accessTokenAuthentication.getAdditionalParameters();
OAuth2AccessTokenResponse.Builder builder = OAuth2AccessTokenResponse.withToken(accessToken.getTokenValue())
.tokenType(accessToken.getTokenType()).scopes(accessToken.getScopes());
if (accessToken.getIssuedAt() != null && accessToken.getExpiresAt() != null) {
builder.expiresIn(ChronoUnit.SECONDS.between(accessToken.getIssuedAt(), accessToken.getExpiresAt()));
}
if (refreshToken != null) {
builder.refreshToken(refreshToken.getTokenValue());
}
if (!CollectionUtils.isEmpty(additionalParameters)) {
builder.additionalParameters(additionalParameters);
}
OAuth2AccessTokenResponse accessTokenResponse = builder.build();
ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
this.accessTokenHttpResponseConverter.write(accessTokenResponse, null, httpResponse);
}
}

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2020 pig4cloud Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.pig4cloud.pig.auth.support.handler;
import cn.hutool.core.collection.CollUtil;
import com.pig4cloud.pig.admin.api.entity.SysLog;
import com.pig4cloud.pig.common.core.util.SpringContextHolder;
import com.pig4cloud.pig.common.core.util.WebUtils;
import com.pig4cloud.pig.common.log.event.SysLogEvent;
import com.pig4cloud.pig.common.log.util.SysLogUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.event.LogoutSuccessEvent;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
import org.springframework.stereotype.Component;
/**
* @author zhangran
* @date 2022-06-02
*
* 事件机制处理退出相关
*/
@Slf4j
@Component
public class PigLogoutSuccessEventHandler implements ApplicationListener<LogoutSuccessEvent> {
@Override
public void onApplicationEvent(LogoutSuccessEvent event) {
Authentication authentication = (Authentication) event.getSource();
if (CollUtil.isNotEmpty(authentication.getAuthorities())) {
handle(authentication);
}
}
/**
* 处理退出成功方法
* <p>
* 获取到登录的authentication 对象
* @param authentication 登录对象
*/
public void handle(Authentication authentication) {
log.info("用户:{} 退出成功", authentication.getPrincipal());
SecurityContextHolder.getContext().setAuthentication(authentication);
SysLog logVo = SysLogUtils.getSysLog();
logVo.setTitle("退出成功");
// 发送异步日志事件
Long startTime = System.currentTimeMillis();
Long endTime = System.currentTimeMillis();
logVo.setTime(endTime - startTime);
// 设置对应的token
WebUtils.getRequest().ifPresent(request -> logVo.setParams(request.getHeader(HttpHeaders.AUTHORIZATION)));
// 这边设置ServiceId
if (authentication instanceof OAuth2Authorization) {
OAuth2Authorization auth2Authentication = (OAuth2Authorization) authentication;
logVo.setServiceId(auth2Authentication.getRegisteredClientId());
}
logVo.setCreateBy(authentication.getName());
logVo.setUpdateBy(authentication.getName());
SpringContextHolder.publishEvent(new SysLogEvent(logVo));
}
}

View File

@ -1,4 +1,4 @@
package com.pig4cloud.pig.common.security.handler; package com.pig4cloud.pig.auth.support.handler;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
@ -11,7 +11,7 @@ import java.io.IOException;
/** /**
* @author lengleng * @author lengleng
* @date 2020/10/6 * @date 2022-06-02
* <p> * <p>
* sso 退出功能 根据客户端传入跳转 * sso 退出功能 根据客户端传入跳转
*/ */

View File

@ -48,8 +48,6 @@ public class SysLogUtils {
HttpServletRequest request = ((ServletRequestAttributes) Objects HttpServletRequest request = ((ServletRequestAttributes) Objects
.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); .requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
SysLog sysLog = new SysLog(); SysLog sysLog = new SysLog();
sysLog.setCreateBy(Objects.requireNonNull(getUsername()));
sysLog.setUpdateBy(Objects.requireNonNull(getUsername()));
sysLog.setType(LogTypeEnum.NORMAL.getType()); sysLog.setType(LogTypeEnum.NORMAL.getType());
sysLog.setRemoteAddr(ServletUtil.getClientIP(request)); sysLog.setRemoteAddr(ServletUtil.getClientIP(request));
sysLog.setRequestUri(URLUtil.getPath(request.getRequestURI())); sysLog.setRequestUri(URLUtil.getPath(request.getRequestURI()));

View File

@ -56,9 +56,9 @@
<artifactId>spring-security-oauth2-jose</artifactId> <artifactId>spring-security-oauth2-jose</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.security</groupId> <groupId>io.springboot.security</groupId>
<artifactId>spring-security-oauth2-authorization-server</artifactId> <artifactId>spring-security-oauth2-authorization-server</artifactId>
<version>0.3.0</version> <version>${spring.authorization.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>

View File

@ -1,24 +1,12 @@
package com.pig4cloud.pig.common.security.component; package com.pig4cloud.pig.common.security.component;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;
import com.pig4cloud.pig.common.security.service.PigRedisOAuth2AuthorizationConsentService; import com.pig4cloud.pig.common.security.service.PigRedisOAuth2AuthorizationConsentService;
import com.pig4cloud.pig.common.security.service.PigRedisOAuth2AuthorizationService; import com.pig4cloud.pig.common.security.service.PigRedisOAuth2AuthorizationService;
import lombok.SneakyThrows;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsent;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService; import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.UUID;
/** /**
* @author lengleng * @author lengleng
* @date 2021/10/16 * @date 2021/10/16
@ -35,22 +23,4 @@ public class PigTokenStoreAutoConfiguration {
return new PigRedisOAuth2AuthorizationConsentService(redisTemplate); return new PigRedisOAuth2AuthorizationConsentService(redisTemplate);
} }
@Bean
@SneakyThrows
public JWKSource<SecurityContext> jwkSource() {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
// @formatter:off
RSAKey rsaKey= new RSAKey.Builder(publicKey)
.privateKey(privateKey)
.keyID(UUID.randomUUID().toString())
.build();
JWKSet jwkSet = new JWKSet(rsaKey);
return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
}
} }

View File

@ -1,51 +0,0 @@
/*
* Copyright (c) 2020 pig4cloud Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.pig4cloud.pig.common.security.handler;
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
/**
* @author lengleng
* @date 2019/2/1 认证失败事件处理器
*/
public abstract class AbstractAuthenticationFailureEventHandler
implements ApplicationListener<AbstractAuthenticationFailureEvent> {
/**
* Handle an application event.
* @param event the event to respond to
*/
@Override
public void onApplicationEvent(AbstractAuthenticationFailureEvent event) {
AuthenticationException authenticationException = event.getException();
Authentication authentication = (Authentication) event.getSource();
handle(authenticationException, authentication);
}
/**
* 处理登录成功方法
* <p>
* @param authenticationException 登录的authentication 对象
* @param authentication 登录的authenticationException 对象
*/
public abstract void handle(AuthenticationException authenticationException, Authentication authentication);
}

View File

@ -1,51 +0,0 @@
/*
* Copyright (c) 2020 pig4cloud Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.pig4cloud.pig.common.security.handler;
import cn.hutool.core.collection.CollUtil;
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.core.Authentication;
/**
* @author lengleng
* @date 2019/2/1 认证成功事件处理器
*/
public abstract class AbstractAuthenticationSuccessEventHandler
implements ApplicationListener<AuthenticationSuccessEvent> {
/**
* Handle an application event.
* @param event the event to respond to
*/
@Override
public void onApplicationEvent(AuthenticationSuccessEvent event) {
Authentication authentication = (Authentication) event.getSource();
if (CollUtil.isNotEmpty(authentication.getAuthorities())) {
handle(authentication);
}
}
/**
* 处理登录成功方法
* <p>
* 获取到登录的authentication 对象
* @param authentication 登录对象
*/
public abstract void handle(Authentication authentication);
}

View File

@ -1,50 +0,0 @@
/*
* Copyright (c) 2020 pig4cloud Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.pig4cloud.pig.common.security.handler;
import cn.hutool.core.collection.CollUtil;
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.LogoutSuccessEvent;
import org.springframework.security.core.Authentication;
/**
* @author zhangran
* @date 2021/6/23 退出成功事件处理器
*/
public abstract class AbstractLogoutSuccessEventHandler implements ApplicationListener<LogoutSuccessEvent> {
/**
* Handle an application event.
* @param event the event to respond to
*/
@Override
public void onApplicationEvent(LogoutSuccessEvent event) {
Authentication authentication = (Authentication) event.getSource();
if (CollUtil.isNotEmpty(authentication.getAuthorities())) {
handle(authentication);
}
}
/**
* 处理退出成功方法
* <p>
* 获取到登录的authentication 对象
* @param authentication 登录对象
*/
public abstract void handle(Authentication authentication);
}

View File

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common</artifactId>
<version>3.4.10</version>
</parent>
<artifactId>pig-common-test</artifactId>
<packaging>jar</packaging>
<description>pig oauth 2.0 单元测试工具类</description>
<dependencies>
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,29 +0,0 @@
package com.pig4cloud.pig.test.annotation;
import com.pig4cloud.pig.test.WithMockSecurityContextFactory;
import org.springframework.security.test.context.support.WithSecurityContext;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* @author lengleng
* @date 2020/9/22
* <p>
* WithMockOAuth2User 注解
*/
@Retention(RetentionPolicy.RUNTIME)
@WithSecurityContext(factory = WithMockSecurityContextFactory.class)
public @interface WithMockOAuth2User {
/**
* 用户名
*/
String username() default "admin";
/**
* 密码
*/
String password() default "123456";
}

View File

@ -1,29 +0,0 @@
package com.pig4cloud.pig.test.kit;
import com.pig4cloud.pig.common.core.util.SpringContextHolder;
import org.springframework.http.HttpHeaders;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.test.web.servlet.request.RequestPostProcessor;
/**
* @author lengleng
* @date 2020/9/22
* <p>
* Mock 工具类
*/
public class OAuthMockKit {
/**
* mock 请求增加统一请求头
* @return RequestPostProcessor 类似于拦截器
*/
public static RequestPostProcessor token() {
return mockRequest -> {
OAuth2ClientContext clientContext = SpringContextHolder.getBean(OAuth2ClientContext.class);
String token = clientContext.getAccessToken().getValue();
mockRequest.addHeader(HttpHeaders.AUTHORIZATION, String.format("Bearer: %s", token));
return mockRequest;
};
}
}

View File

@ -40,6 +40,5 @@
<module>pig-common-security</module> <module>pig-common-security</module>
<module>pig-common-feign</module> <module>pig-common-feign</module>
<module>pig-common-swagger</module> <module>pig-common-swagger</module>
<!-- <module>pig-common-test</module>-->
</modules> </modules>
</project> </project>

View File

@ -0,0 +1,30 @@
package com.pig4cloud.pig.admin.api.vo;
import lombok.Data;
import java.time.Instant;
/**
* 前端展示令牌管理
*
* @author lengleng
* @date 2022/6/2
*/
@Data
public class TokenVo {
private String id;
private Long userId;
private String clientId;
private String username;
private String accessToken;
private Instant issuedAt;
private Instant expiresAt;
}

View File

@ -170,7 +170,7 @@ public class UserController {
* @return 用户集合 * @return 用户集合
*/ */
@GetMapping("/page") @GetMapping("/page")
public R<IPage<List<UserVO>>> getUserPage(Page page, UserDTO userDTO) { public R<IPage<UserVO>> getUserPage(Page page, UserDTO userDTO) {
return R.ok(userService.getUserWithRolePage(page, userDTO)); return R.ok(userService.getUserWithRolePage(page, userDTO));
} }

View File

@ -51,7 +51,7 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
* @param userDTO 查询参数 * @param userDTO 查询参数
* @return list * @return list
*/ */
IPage<List<UserVO>> getUserVosPage(Page page, @Param("query") UserDTO userDTO); IPage<UserVO> getUserVosPage(Page page, @Param("query") UserDTO userDTO);
/** /**
* 通过ID查询用户信息 * 通过ID查询用户信息

View File

@ -49,7 +49,7 @@ public interface SysUserService extends IService<SysUser> {
* @param userDTO 参数列表 * @param userDTO 参数列表
* @return * @return
*/ */
IPage<List<UserVO>> getUserWithRolePage(Page page, UserDTO userDTO); IPage<UserVO> getUserWithRolePage(Page page, UserDTO userDTO);
/** /**
* 删除用户 * 删除用户

View File

@ -142,7 +142,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
* @return * @return
*/ */
@Override @Override
public IPage<List<UserVO>> getUserWithRolePage(Page page, UserDTO userDTO) { public IPage<UserVO> getUserWithRolePage(Page page, UserDTO userDTO) {
return baseMapper.getUserVosPage(page, userDTO); return baseMapper.getUserVosPage(page, userDTO);
} }

View File

@ -34,6 +34,7 @@
<maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.target>1.8</maven.compiler.target>
<spring-boot-admin.version>2.6.7</spring-boot-admin.version> <spring-boot-admin.version>2.6.7</spring-boot-admin.version>
<spring.authorization.version>0.3.0</spring.authorization.version>
<hutool.version>5.8.2</hutool.version> <hutool.version>5.8.2</hutool.version>
<dynamic-ds.version>3.5.1</dynamic-ds.version> <dynamic-ds.version>3.5.1</dynamic-ds.version>
<captcha.version>2.2.2</captcha.version> <captcha.version>2.2.2</captcha.version>