♻️ 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-security -- 安全工具类
├── pig-common-swagger -- 接口文档
├── pig-common-feign -- feign 扩展封装
└── pig-common-test -- oauth2.0 单元测试扩展封装
└── pig-common-feign -- feign 扩展封装
├── pig-register -- Nacos Server[8848]
├── pig-gateway -- Spring Cloud Gateway网关[9999]
└── pig-upms -- 通用用户权限管理模块

View File

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

View File

@ -16,16 +16,14 @@
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.handler.FormAuthenticationFailureHandler;
import com.pig4cloud.pig.common.security.handler.SsoLogoutSuccessHandler;
import org.springframework.context.annotation.Bean;
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.WebSecurityCustomizer;
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()
// 个性化 formLogin
.formLogin().loginPage("/token/login").loginProcessingUrl("/token/form")
.failureHandler(authenticationFailureHandler()).and().logout()
.logoutSuccessHandler(logoutSuccessHandler()).deleteCookies("JSESSIONID").invalidateHttpSession(true);
// SSO登录失败处理
.failureHandler(new FormAuthenticationFailureHandler()).and().logout()
// SSO登出成功处理
.logoutSuccessHandler(new SsoLogoutSuccessHandler()).deleteCookies("JSESSIONID")
.invalidateHttpSession(true);
// 处理 UsernamePasswordAuthenticationToken
http.authenticationProvider(new PigDaoAuthenticationProvider());
@ -65,22 +66,4 @@ public class WebSecurityConfiguration {
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.pig4cloud.pig.admin.api.entity.SysOauthClientDetails;
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.OAuth2ErrorCodesExpand;
import com.pig4cloud.pig.common.core.constant.CacheConstants;
@ -80,7 +81,7 @@ public class PigTokenEndpoint {
private final RemoteClientDetailsService clientDetailsService;
private final RedisTemplate redisTemplate;
private final RedisTemplate<String, Object> redisTemplate;
private final CacheManager cacheManager;
@ -192,7 +193,20 @@ public class PigTokenEndpoint {
Set<String> keys = redisTemplate.keys(key);
List<String> pages = keys.stream().skip((current - 1) * size).limit(size).collect(Collectors.toList());
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());
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(),
context.getPrincipal().getName(), UUID.randomUUID());
return new CustomeOAuth2AccessTokenGenerator.OAuth2AccessTokenClaims(
OAuth2AccessToken.TokenType.BEARER, key, accessTokenClaimsSet.getIssuedAt(),
accessTokenClaimsSet.getExpiresAt(), context.getAuthorizedScopes(), accessTokenClaimsSet.getClaims());
return new CustomeOAuth2AccessTokenGenerator.OAuth2AccessTokenClaims(OAuth2AccessToken.TokenType.BEARER, key,
accessTokenClaimsSet.getIssuedAt(), accessTokenClaimsSet.getExpiresAt(), context.getAuthorizedScopes(),
accessTokenClaimsSet.getClaims());
}
/**

View File

@ -14,7 +14,7 @@
* 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.http.HttpUtil;
@ -29,7 +29,7 @@ import javax.servlet.http.HttpServletResponse;
/**
* @author lengleng
* @date 2019-08-20
* @date 2022-06-02
* <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 org.springframework.http.HttpHeaders;
@ -11,7 +11,7 @@ import java.io.IOException;
/**
* @author lengleng
* @date 2020/10/6
* @date 2022-06-02
* <p>
* sso 退出功能 根据客户端传入跳转
*/

View File

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

View File

@ -56,17 +56,17 @@
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<groupId>io.springboot.security</groupId>
<artifactId>spring-security-oauth2-authorization-server</artifactId>
<version>0.3.0</version>
<version>${spring.authorization.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
</dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,24 +1,12 @@
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.PigRedisOAuth2AuthorizationService;
import lombok.SneakyThrows;
import org.springframework.context.annotation.Bean;
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.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
* @date 2021/10/16
@ -35,22 +23,4 @@ public class PigTokenStoreAutoConfiguration {
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-feign</module>
<module>pig-common-swagger</module>
<!-- <module>pig-common-test</module>-->
</modules>
</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 用户集合
*/
@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));
}

View File

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

View File

@ -49,7 +49,7 @@ public interface SysUserService extends IService<SysUser> {
* @param userDTO 参数列表
* @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
*/
@Override
public IPage<List<UserVO>> getUserWithRolePage(Page page, UserDTO userDTO) {
public IPage<UserVO> getUserWithRolePage(Page page, UserDTO userDTO) {
return baseMapper.getUserVosPage(page, userDTO);
}

441
pom.xml
View File

@ -16,231 +16,232 @@
~ limitations under the License.
-->
<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>
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>
<groupId>com.pig4cloud</groupId>
<artifactId>pig</artifactId>
<name>${project.artifactId}</name>
<version>3.5.0-SNAPSHOT</version>
<packaging>pom</packaging>
<url>https://www.pig4cloud.com</url>
<groupId>com.pig4cloud</groupId>
<artifactId>pig</artifactId>
<name>${project.artifactId}</name>
<version>3.5.0-SNAPSHOT</version>
<packaging>pom</packaging>
<url>https://www.pig4cloud.com</url>
<properties>
<spring-boot.version>2.7.0</spring-boot.version>
<spring-cloud.version>2021.0.3</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring-boot-admin.version>2.6.7</spring-boot-admin.version>
<hutool.version>5.8.2</hutool.version>
<dynamic-ds.version>3.5.1</dynamic-ds.version>
<captcha.version>2.2.2</captcha.version>
<velocity.version>2.3</velocity.version>
<velocity.tool.version>3.1</velocity.tool.version>
<configuration.version>1.10</configuration.version>
<jasypt.version>2.1.0</jasypt.version>
<swagger.fox.version>3.0.0</swagger.fox.version>
<xxl-job.version>2.3.1</xxl-job.version>
<docker.plugin.version>0.32.0</docker.plugin.version>
<docker.host>http://192.168.0.100:2375</docker.host>
<docker.registry>192.168.0.100</docker.registry>
<docker.namespace>pig4cloud</docker.namespace>
<docker.username>username</docker.username>
<docker.password>password</docker.password>
<git.commit.plugin>4.9.9</git.commit.plugin>
<spring.checkstyle.plugin>0.0.32</spring.checkstyle.plugin>
</properties>
<properties>
<spring-boot.version>2.7.0</spring-boot.version>
<spring-cloud.version>2021.0.3</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<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>
<dynamic-ds.version>3.5.1</dynamic-ds.version>
<captcha.version>2.2.2</captcha.version>
<velocity.version>2.3</velocity.version>
<velocity.tool.version>3.1</velocity.tool.version>
<configuration.version>1.10</configuration.version>
<jasypt.version>2.1.0</jasypt.version>
<swagger.fox.version>3.0.0</swagger.fox.version>
<xxl-job.version>2.3.1</xxl-job.version>
<docker.plugin.version>0.32.0</docker.plugin.version>
<docker.host>http://192.168.0.100:2375</docker.host>
<docker.registry>192.168.0.100</docker.registry>
<docker.namespace>pig4cloud</docker.namespace>
<docker.username>username</docker.username>
<docker.password>password</docker.password>
<git.commit.plugin>4.9.9</git.commit.plugin>
<spring.checkstyle.plugin>0.0.32</spring.checkstyle.plugin>
</properties>
<!-- 以下依赖 全局所有的模块都会引入 -->
<dependencies>
<!--配置文件处理器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--配置文件加解密-->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>${jasypt.version}</version>
</dependency>
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--监控客户端-->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>${spring-boot-admin.version}</version>
</dependency>
<!--Lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!--测试依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 以下依赖 全局所有的模块都会引入 -->
<dependencies>
<!--配置文件处理器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--配置文件加解密-->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>${jasypt.version}</version>
</dependency>
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--监控客户端-->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>${spring-boot-admin.version}</version>
</dependency>
<!--Lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!--测试依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<modules>
<module>pig-register</module>
<module>pig-gateway</module>
<module>pig-auth</module>
<module>pig-upms</module>
<module>pig-common</module>
<module>pig-visual</module>
</modules>
<modules>
<module>pig-register</module>
<module>pig-gateway</module>
<module>pig-auth</module>
<module>pig-upms</module>
<module>pig-common</module>
<module>pig-visual</module>
</modules>
<dependencyManagement>
<dependencies>
<!--pig 公共版本定义-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common-bom</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring boot 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring cloud 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring cloud alibaba 依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencyManagement>
<dependencies>
<!--pig 公共版本定义-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common-bom</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring boot 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring cloud 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring cloud alibaba 依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>${project.name}</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<finalName>${project.build.finalName}</finalName>
<layers>
<enabled>true</enabled>
</layers>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>${docker.plugin.version}</version>
<configuration>
<!-- Docker Remote Api-->
<dockerHost>${docker.host}</dockerHost>
<!-- Docker 镜像私服-->
<registry>${docker.registry}</registry>
<!-- 认证信息-->
<authConfig>
<push>
<username>${docker.username}</username>
<password>${docker.password}</password>
</push>
</authConfig>
<images>
<image>
<!-- 镜像名称: 172.17.0.111/library/pig-gateway:2.6.3-->
<name>${docker.registry}/${docker.namespace}/${project.name}:${project.version}</name>
<build>
<dockerFile>${project.basedir}/Dockerfile</dockerFile>
</build>
</image>
</images>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<!--打包jar 与git commit 关联插件-->
<plugin>
<groupId>io.github.git-commit-id</groupId>
<artifactId>git-commit-id-maven-plugin</artifactId>
<version>${git.commit.plugin}</version>
<executions>
<execution>
<id>get-the-git-infos</id>
<goals>
<goal>revision</goal>
</goals>
<phase>initialize</phase>
</execution>
</executions>
<configuration>
<failOnNoGitDirectory>false</failOnNoGitDirectory>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
<!--因为项目定制了jackson的日期时间序列化/反序列化格式,因此这里要进行配置,不然通过management.info.git.mode=full进行完整git信息监控时会存在问题-->
<dateFormat>yyyy-MM-dd HH:mm:ss</dateFormat>
<includeOnlyProperties>
<includeOnlyProperty>^git.build.(time|version)$</includeOnlyProperty>
<includeOnlyProperty>^git.commit.(id|message|time).*$</includeOnlyProperty>
</includeOnlyProperties>
</configuration>
</plugin>
<!--代码格式插件默认使用spring 规则-->
<plugin>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-maven-plugin</artifactId>
<version>${spring.checkstyle.plugin}</version>
</plugin>
</plugins>
</build>
<build>
<finalName>${project.name}</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<finalName>${project.build.finalName}</finalName>
<layers>
<enabled>true</enabled>
</layers>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>${docker.plugin.version}</version>
<configuration>
<!-- Docker Remote Api-->
<dockerHost>${docker.host}</dockerHost>
<!-- Docker 镜像私服-->
<registry>${docker.registry}</registry>
<!-- 认证信息-->
<authConfig>
<push>
<username>${docker.username}</username>
<password>${docker.password}</password>
</push>
</authConfig>
<images>
<image>
<!-- 镜像名称: 172.17.0.111/library/pig-gateway:2.6.3-->
<name>${docker.registry}/${docker.namespace}/${project.name}:${project.version}</name>
<build>
<dockerFile>${project.basedir}/Dockerfile</dockerFile>
</build>
</image>
</images>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<!--打包jar 与git commit 关联插件-->
<plugin>
<groupId>io.github.git-commit-id</groupId>
<artifactId>git-commit-id-maven-plugin</artifactId>
<version>${git.commit.plugin}</version>
<executions>
<execution>
<id>get-the-git-infos</id>
<goals>
<goal>revision</goal>
</goals>
<phase>initialize</phase>
</execution>
</executions>
<configuration>
<failOnNoGitDirectory>false</failOnNoGitDirectory>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
<!--因为项目定制了jackson的日期时间序列化/反序列化格式,因此这里要进行配置,不然通过management.info.git.mode=full进行完整git信息监控时会存在问题-->
<dateFormat>yyyy-MM-dd HH:mm:ss</dateFormat>
<includeOnlyProperties>
<includeOnlyProperty>^git.build.(time|version)$</includeOnlyProperty>
<includeOnlyProperty>^git.commit.(id|message|time).*$</includeOnlyProperty>
</includeOnlyProperties>
</configuration>
</plugin>
<!--代码格式插件默认使用spring 规则-->
<plugin>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-maven-plugin</artifactId>
<version>${spring.checkstyle.plugin}</version>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>dev</id>
<properties>
<!-- 环境标识,需要与配置文件的名称相对应 -->
<profiles.active>dev</profiles.active>
</properties>
<activation>
<!-- 默认环境 -->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
<profiles>
<profile>
<id>dev</id>
<properties>
<!-- 环境标识,需要与配置文件的名称相对应 -->
<profiles.active>dev</profiles.active>
</properties>
<activation>
<!-- 默认环境 -->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
</project>