核心模块-security
This commit is contained in:
parent
84d5e8fe13
commit
486dd07e43
@ -38,6 +38,11 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<!-- jwt 相关依赖-->
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt</artifactId>
|
||||
</dependency>
|
||||
<!--Redis-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@ -57,6 +62,11 @@
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>easyexcel</artifactId>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-compress -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package com.cpop.core.aspect;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.cpop.common.constant.HttpStatus;
|
||||
import com.cpop.common.enums.ErrorCodeEnum;
|
||||
import com.cpop.core.base.R;
|
||||
@ -11,6 +10,7 @@ import com.cpop.core.base.table.SysOperationLog;
|
||||
import com.cpop.core.event.OperationLogEvent;
|
||||
import com.cpop.core.utils.MessageUtils;
|
||||
import com.cpop.core.utils.SecurityUtils;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.*;
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
package com.cpop.core.base.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author DB
|
||||
* @create 2023-04-05 17:53
|
||||
*/
|
||||
@Data
|
||||
public class LoginForm implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 单次标识
|
||||
*/
|
||||
private String userKey;
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.cpop.core.base.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author: DB
|
||||
* @date: 2022-09-26 22:48
|
||||
* @Description: 登录成功vo
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class LoginSuccess implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
private String userId;
|
||||
|
||||
/**
|
||||
* token
|
||||
*/
|
||||
private String token;
|
||||
|
||||
/**
|
||||
* 权限
|
||||
*/
|
||||
private Set<String> role;
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package com.cpop.core.base.entity.loginInfo;
|
||||
|
||||
import com.cpop.core.base.table.SysUser;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* @author DB
|
||||
* @createTime 2023/09/10 13:02
|
||||
* @description 系统员工登陆信息
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class OamStaffLoginInfo extends SysUser {
|
||||
|
||||
/**
|
||||
* 员工id(staffId)
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 姓名
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 部门id
|
||||
*/
|
||||
private String deptId;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
private String userId;
|
||||
|
||||
/**
|
||||
* 员工类型(0:技术人员;1:售后人员;2:管理人员)
|
||||
*/
|
||||
private Integer staffType;
|
||||
|
||||
/**
|
||||
* 角色id
|
||||
*/
|
||||
private String roleId;
|
||||
}
|
||||
@ -9,7 +9,14 @@ import lombok.Getter;
|
||||
*/
|
||||
@Getter
|
||||
public enum OperationLogEnum {
|
||||
|
||||
/**
|
||||
* 系统登录
|
||||
*/
|
||||
SYSTEM_LOGIN(0, "i18n_operationLog_systemLogin", "SystemLoginModel", 6, 4),
|
||||
/**
|
||||
* 系统用户退出登录
|
||||
*/
|
||||
SYSTEM_LOGOUT(1, "i18n_operationLog_systemLogout", "SystemLoginModel", 6, 4),
|
||||
;
|
||||
|
||||
/**
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
package com.cpop.core.base.exception;
|
||||
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
|
||||
/**
|
||||
* @author: DB
|
||||
* @Date: 2023/08/24/18:10
|
||||
* @Description: 自定义认证失败异常
|
||||
*/
|
||||
public class CpopAuthenticationException extends AuthenticationException {
|
||||
|
||||
private Object params;
|
||||
|
||||
public CpopAuthenticationException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public CpopAuthenticationException(String msg, Object params) {
|
||||
super(msg);
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public Object getParams() {
|
||||
return params;
|
||||
}
|
||||
}
|
||||
@ -47,7 +47,7 @@ public class CpopConfig {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public static String getProfile() {
|
||||
public String getProfile() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
@ -66,28 +66,28 @@ public class CpopConfig {
|
||||
/**
|
||||
* 获取导入上传路径
|
||||
*/
|
||||
public static String getImportPath() {
|
||||
public String getImportPath() {
|
||||
return getProfile() + "/import";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取头像上传路径
|
||||
*/
|
||||
public static String getAvatarPath() {
|
||||
public String getAvatarPath() {
|
||||
return getProfile() + "/avatar";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下载路径
|
||||
*/
|
||||
public static String getDownloadPath() {
|
||||
public String getDownloadPath() {
|
||||
return getProfile() + "/download/";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上传路径
|
||||
*/
|
||||
public static String getUploadPath() {
|
||||
public String getUploadPath() {
|
||||
return getProfile() + "/upload";
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,67 @@
|
||||
package com.cpop.core.config;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author DB
|
||||
* @Description: 生成密钥对的配置文件
|
||||
* @create: 2023-08-04 23:06
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "cpop.gateway.rsa-keypair")
|
||||
public class GenerateKeyPairConfig {
|
||||
|
||||
/**
|
||||
* 加密方式
|
||||
*/
|
||||
private String algorithm;
|
||||
|
||||
/**
|
||||
* 初始化大小
|
||||
*/
|
||||
private Integer keySize;
|
||||
|
||||
/**
|
||||
* 公钥文件
|
||||
*/
|
||||
private String publicKeyFile;
|
||||
|
||||
/**
|
||||
* 私钥文件
|
||||
*/
|
||||
private String privateKeyFile;
|
||||
|
||||
/**
|
||||
* 获取指定加密算法
|
||||
* @return 读取YAML文件的 SystemConfig.rsa-keypair.algorithm 属性
|
||||
*/
|
||||
public String getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取密钥长度,用来初始化
|
||||
* @return 读取YAML文件的 SystemConfig.rsa-keypair.key-size 属性
|
||||
*/
|
||||
public Integer getKeySize() {
|
||||
return keySize;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取公钥存放文件
|
||||
* @return 读取YAML文件的 SystemConfig.rsa-keypair.public-key-file 属性
|
||||
*/
|
||||
public String getPublicKeyFile() {
|
||||
return publicKeyFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取私钥存放文件
|
||||
* @return 读取YAML文件的 SystemConfig.rsa-keypair.private-key-file 属性
|
||||
*/
|
||||
public String getPrivateKeyFile() {
|
||||
return privateKeyFile;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
package com.cpop.core.config;
|
||||
|
||||
import com.mybatisflex.core.mybatis.FlexConfiguration;
|
||||
import com.mybatisflex.spring.boot.ConfigurationCustomizer;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author DB
|
||||
* @Description:
|
||||
* @create 2023-08-27 12:13
|
||||
*/
|
||||
@Configuration
|
||||
public class MybatisFlexConfig implements ConfigurationCustomizer {
|
||||
|
||||
@Override
|
||||
public void customize(FlexConfiguration configuration) {
|
||||
// 在这里为 configuration 进行配置
|
||||
}
|
||||
}
|
||||
225
Cpop-Core/src/main/java/com/cpop/core/config/SecurityConfig.java
Normal file
225
Cpop-Core/src/main/java/com/cpop/core/config/SecurityConfig.java
Normal file
@ -0,0 +1,225 @@
|
||||
package com.cpop.core.config;
|
||||
|
||||
import com.cpop.common.constant.Constants;
|
||||
import com.cpop.common.utils.StringUtils;
|
||||
import com.cpop.core.filter.JwtAuthenticationFilter;
|
||||
import com.cpop.core.filter.RepeatableFilter;
|
||||
import com.cpop.core.gateway.miniProgram.MiniProgramAuthenticationFilter;
|
||||
import com.cpop.core.gateway.miniProgram.MiniProgramAuthenticationProvider;
|
||||
import com.cpop.core.gateway.oam.OamUsernamePasswordAuthenticationFilter;
|
||||
import com.cpop.core.handler.*;
|
||||
import com.cpop.core.service.impl.OamStaffDetailsServiceImpl;
|
||||
import com.cpop.core.utils.JwtUtils;
|
||||
import com.cpop.core.utils.PasswordEncoder;
|
||||
import com.cpop.core.utils.SpringUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
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.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author DB
|
||||
* @Description: Security配置中心
|
||||
* @since 2023-08-05 8:01
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@RequiredArgsConstructor
|
||||
@EnableMethodSecurity
|
||||
public class SecurityConfig implements WebMvcConfigurer {
|
||||
|
||||
@Autowired
|
||||
private JwtLogoutSuccessHandler jwtLogoutSuccessHandler;
|
||||
|
||||
@Autowired
|
||||
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
|
||||
|
||||
@Autowired
|
||||
private JwtAccessDeniedHandler jwtAccessDeniedHandler;
|
||||
|
||||
@Autowired
|
||||
private RepeatableFilter repeatableFilter;
|
||||
|
||||
@Autowired
|
||||
private LoginSuccessHandler loginSuccessHandler;
|
||||
|
||||
@Autowired
|
||||
private LoginFailureHandler loginFailureHandler;
|
||||
|
||||
@Autowired
|
||||
private CpopConfig cpopConfig;
|
||||
|
||||
@Autowired
|
||||
private JwtUtils jwtUtils;
|
||||
|
||||
/**
|
||||
* Security过滤拦截配置
|
||||
*
|
||||
* @param http 请求
|
||||
* @return SecurityFilterChain 认证过滤链
|
||||
* @throws Exception 异常
|
||||
*/
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.cors(AbstractHttpConfigurer::disable)
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
//登录配置(多登陆模式自定义成功与失败->现已注释)
|
||||
/*.formLogin(formLogin -> {
|
||||
formLogin.successHandler(loginSuccessHandler)
|
||||
.failureHandler(loginFailureHandler);
|
||||
})*/
|
||||
//登出配置
|
||||
.logout(logout -> logout.logoutSuccessHandler(jwtLogoutSuccessHandler))
|
||||
//禁用session
|
||||
.sessionManagement(sessionManagement -> {
|
||||
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
||||
})
|
||||
//配置拦截规则
|
||||
.authorizeHttpRequests(authorizeHttpRequests -> {
|
||||
authorizeHttpRequests.antMatchers(StringUtils.split(jwtUtils.getWhiteList(), ",")).permitAll()
|
||||
.anyRequest().authenticated();
|
||||
})
|
||||
//异常处理器
|
||||
.exceptionHandling(exceptionHandling -> {
|
||||
exceptionHandling.authenticationEntryPoint(jwtAuthenticationEntryPoint)
|
||||
.accessDeniedHandler(jwtAccessDeniedHandler);
|
||||
})
|
||||
//自定义认证管理器
|
||||
.authenticationManager(authenticationManager())
|
||||
//流重复使用
|
||||
.addFilterBefore(repeatableFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
// 添加 JWT 过滤器,JWT 过滤器在退出认证过滤器之前
|
||||
.addFilterBefore(authFilter(), LogoutFilter.class)
|
||||
.addFilterAt(oamLoginFilter(http.getSharedObject(AuthenticationManager.class)), UsernamePasswordAuthenticationFilter.class)
|
||||
//小程序认证
|
||||
.addFilterAt(miniProgramAuthenticationFilter(http.getSharedObject(AuthenticationManager.class)), UsernamePasswordAuthenticationFilter.class);
|
||||
return http.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义用户密码过滤器
|
||||
*
|
||||
* @param authenticationManager 认证管理器
|
||||
* @return OamUsernamePasswordAuthenticationFilter oma管理器
|
||||
*/
|
||||
@Bean
|
||||
public OamUsernamePasswordAuthenticationFilter oamLoginFilter(AuthenticationManager authenticationManager) {
|
||||
OamUsernamePasswordAuthenticationFilter loginFilter = new OamUsernamePasswordAuthenticationFilter();
|
||||
loginFilter.setFilterProcessesUrl("/login");
|
||||
loginFilter.setAuthenticationManager(authenticationManager);
|
||||
loginFilter.setAuthenticationSuccessHandler(loginSuccessHandler);
|
||||
loginFilter.setAuthenticationFailureHandler(loginFailureHandler);
|
||||
return loginFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description: 默认的认证方式
|
||||
* @return DaoAuthenticationProvider
|
||||
* @author DB
|
||||
* @Date: 2023/8/24 0024 16:37
|
||||
*/
|
||||
@Bean
|
||||
public DaoAuthenticationProvider authenticationProvider() {
|
||||
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
|
||||
authProvider.setUserDetailsService(SpringUtils.getBean(OamStaffDetailsServiceImpl.class));
|
||||
authProvider.setPasswordEncoder(passwordEncoder());
|
||||
return authProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description: 小程序登陆认证方式(可自定义其他模式)
|
||||
* @param authenticationManager 认证管理器
|
||||
* @return MiniProgramAuthenticationFilter
|
||||
* @author DB
|
||||
* @Date: 2023/8/24 0024 10:43
|
||||
*/
|
||||
@Bean
|
||||
public MiniProgramAuthenticationFilter miniProgramAuthenticationFilter(AuthenticationManager authenticationManager) {
|
||||
MiniProgramAuthenticationFilter filter = new MiniProgramAuthenticationFilter();
|
||||
filter.setAuthenticationManager(authenticationManager);
|
||||
filter.setAuthenticationSuccessHandler(loginSuccessHandler);
|
||||
filter.setAuthenticationFailureHandler(loginFailureHandler);
|
||||
return filter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MiniProgramAuthenticationProvider miniProgramAuthenticationProvider() {
|
||||
return new MiniProgramAuthenticationProvider();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取AuthenticationManager(认证管理器),登录时认证使用
|
||||
* @return AuthenticationManager
|
||||
*/
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager(){
|
||||
return new ProviderManager(Arrays.asList(authenticationProvider(), miniProgramAuthenticationProvider()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 密码明文加密方式配置
|
||||
* @return PasswordEncoder
|
||||
*/
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new PasswordEncoder();
|
||||
}
|
||||
|
||||
/**
|
||||
* jwt 校验过滤器,从 http 头部 Authorization 字段读取 token 并校验
|
||||
* @return JwtAuthenticationFilter
|
||||
*/
|
||||
@Bean
|
||||
public JwtAuthenticationFilter authFilter() {
|
||||
return new JwtAuthenticationFilter();
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置跨源访问(CORS)
|
||||
* @return CorsConfigurationSource
|
||||
*/
|
||||
@Bean
|
||||
public CorsConfigurationSource corsConfigurationSource() {
|
||||
CorsConfiguration configuration = new CorsConfiguration();
|
||||
configuration.setAllowedOrigins(Collections.singletonList("*"));
|
||||
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
|
||||
configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"));
|
||||
configuration.applyPermitDefaultValues();
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", configuration);
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param registry 资源注册
|
||||
* @Description: 资源映射
|
||||
* @Author DB
|
||||
* @Date: 2023/5/27 13:57
|
||||
*/
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
//本地文件上传路径
|
||||
registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**")
|
||||
.addResourceLocations("file:" + cpopConfig.getProfile() + "/");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,125 @@
|
||||
package com.cpop.core.filter;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.cpop.common.constant.Constants;
|
||||
import com.cpop.common.utils.StringUtils;
|
||||
import com.cpop.common.utils.ip.IpUtils;
|
||||
import com.cpop.core.base.entity.LoginUser;
|
||||
import com.cpop.core.base.enums.UserType;
|
||||
import com.cpop.core.service.RedisService;
|
||||
import com.cpop.core.utils.JwtUtils;
|
||||
import com.pupu.core.security.miniProgram.MiniProgramAuthenticationToken;
|
||||
import com.pupu.core.service.impl.OamStaffDetailsServiceImpl;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jws;
|
||||
import io.jsonwebtoken.JwtException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author: DB
|
||||
* @date: 2022-09-25 16:34
|
||||
* @Description: jwt认证过滤器
|
||||
*/
|
||||
@Component
|
||||
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
@Autowired
|
||||
private JwtUtils jwtUtils;
|
||||
|
||||
@Autowired
|
||||
private OamStaffDetailsServiceImpl oamStaffDetailsService;
|
||||
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
String jwt = request.getHeader(jwtUtils.getHeader());
|
||||
// 这里如果没有jwt,继续往后走,因为后面还有鉴权管理器等去判断是否拥有身份凭证,所以是可以放行的
|
||||
// 没有jwt相当于匿名访问,若有一些接口是需要权限的,则不能访问这些接口
|
||||
if (StringUtils.isEmpty(jwt)) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
Jws<Claims> jws = jwtUtils.getClaimsByToken(jwt);
|
||||
Claims claim = jws.getBody();
|
||||
if (claim == null) {
|
||||
throw new JwtException("token 异常");
|
||||
}
|
||||
if (jwtUtils.isTokenExpired(claim)) {
|
||||
throw new JwtException("token 已过期");
|
||||
}
|
||||
String username = claim.getSubject();
|
||||
UserType userType = UserType.valueOf(jws.getHeader().get(Constants.USER_TYPE).toString());
|
||||
//从缓存中获取
|
||||
JSONObject jsonObject = redisService.getCacheObject(userType.getKey() + username);
|
||||
LoginUser loginUser;
|
||||
if (null == jsonObject){
|
||||
loginUser = multipleLoadUser(userType, username);
|
||||
//存入缓存
|
||||
redisService.setCacheObject(userType.getKey() + username, loginUser);
|
||||
} else {
|
||||
loginUser = jsonObject.toJavaObject(LoginUser.class);
|
||||
}
|
||||
//获取当前请求ip
|
||||
loginUser.setIpAddr(IpUtils.getIpAddr(request));
|
||||
multipleAuth(loginUser,username);
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @descriptions 多种获取用户信息
|
||||
* @author DB
|
||||
* @date 2023/09/11 13:49
|
||||
* @param userType 用户类型
|
||||
* @param username 用户名
|
||||
* @return com.pupu.core.base.entity.LoginUser
|
||||
*/
|
||||
private LoginUser multipleLoadUser(UserType userType, String username) {
|
||||
LoginUser loginUser = null;
|
||||
switch (userType) {
|
||||
//OAM
|
||||
case OAM_USER:
|
||||
// 获取用户的权限等信息
|
||||
loginUser = (LoginUser) oamStaffDetailsService.loadUserByUsername(username);
|
||||
break;
|
||||
case MINI_USER:
|
||||
break;
|
||||
default:
|
||||
}
|
||||
return loginUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description: 多种认证方式
|
||||
* @param loginUser 登陆用户信息
|
||||
* @author DB
|
||||
* @Date: 2023/8/24 0024 17:12
|
||||
*/
|
||||
private void multipleAuth(LoginUser loginUser, String username) {
|
||||
switch (loginUser.getUserType()) {
|
||||
case OAM_USER:
|
||||
// 构建UsernamePasswordAuthenticationToken,这里密码为null,是因为提供了正确的JWT,实现自动登录
|
||||
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, null);
|
||||
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
|
||||
break;
|
||||
case MINI_USER:
|
||||
// MiniProgramAuthenticationToken,实现自动登录
|
||||
MiniProgramAuthenticationToken miniProgramAuthenticationToken = new MiniProgramAuthenticationToken(username, loginUser);
|
||||
SecurityContextHolder.getContext().setAuthentication(miniProgramAuthenticationToken);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package com.cpop.core.gateway.miniProgram;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author DB
|
||||
* @Description: 小程序认证过滤器
|
||||
* @create 2023-08-23 21:03
|
||||
*/
|
||||
public class MiniProgramAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
|
||||
|
||||
|
||||
public MiniProgramAuthenticationFilter() {
|
||||
super(new AntPathRequestMatcher("/miniProgramLogin", "POST"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
|
||||
if (!"POST".equals(request.getMethod())) {
|
||||
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
|
||||
}
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
InputStream inputStream;
|
||||
Map authenticationBean;
|
||||
try {
|
||||
inputStream = request.getInputStream();
|
||||
authenticationBean = mapper.readValue(inputStream, Map.class);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
String username = (String) authenticationBean.get("username");
|
||||
String password = (String) authenticationBean.get("password");
|
||||
username = username.trim();
|
||||
MiniProgramAuthenticationToken authRequest = new MiniProgramAuthenticationToken(username, password);
|
||||
this.setDetails(request, authRequest);
|
||||
return this.getAuthenticationManager().authenticate(authRequest);
|
||||
}
|
||||
|
||||
protected void setDetails(HttpServletRequest request, AbstractAuthenticationToken authRequest) {
|
||||
authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package com.cpop.core.gateway.miniProgram;
|
||||
|
||||
import com.cpop.core.base.entity.LoginUser;
|
||||
import com.cpop.core.base.enums.UserType;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
|
||||
/**
|
||||
* @author DB
|
||||
* @Description: 自定义校验过程
|
||||
* @create 2023-08-23 21:13
|
||||
*/
|
||||
public class MiniProgramAuthenticationProvider implements AuthenticationProvider {
|
||||
|
||||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
// 这个获取表单输入中返回的用户名;
|
||||
String username = authentication.getName();
|
||||
// 这个是表单中输入的密码;
|
||||
String password = (String)authentication.getCredentials();
|
||||
//TODO:此处添加小程序认证失败返回 throw new RockBladeAuthenticationException("测试抛异常", UserType.MINI_USER);
|
||||
//设置用户详情
|
||||
LoginUser loginUser = new LoginUser();
|
||||
loginUser.setUserName(username)
|
||||
.setUserType(UserType.MINI_USER);
|
||||
MiniProgramAuthenticationToken result = new MiniProgramAuthenticationToken(username, loginUser);
|
||||
result.setDetails(loginUser);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> authentication) {
|
||||
//providerManager会遍历所有;securityConfig中注册的provider集合;根据此方法返回true或false来决定由哪个provider;去校验请求过来的authentication
|
||||
return (MiniProgramAuthenticationToken.class.isAssignableFrom(authentication));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
package com.cpop.core.gateway.miniProgram;
|
||||
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author DB
|
||||
* @Description:
|
||||
* @create 2023-08-23 21:11
|
||||
*/
|
||||
public class MiniProgramAuthenticationToken extends AbstractAuthenticationToken {
|
||||
|
||||
private final Object principal;
|
||||
private Object credentials;
|
||||
|
||||
/**
|
||||
* This constructor can be safely used by any code that wishes to create a
|
||||
* <code>UsernamePasswordAuthenticationToken</code>, as the {@link #isAuthenticated()}
|
||||
* will return <code>false</code>.
|
||||
*
|
||||
*/
|
||||
public MiniProgramAuthenticationToken(Object principal, Object credentials) {
|
||||
super(null);
|
||||
this.principal = principal;
|
||||
this.credentials = credentials;
|
||||
setAuthenticated(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructor should only be used by <code>AuthenticationManager</code> or
|
||||
* <code>AuthenticationProvider</code> implementations that are satisfied with
|
||||
* producing a trusted (i.e. {@link #isAuthenticated()} = <code>true</code>)
|
||||
* authentication token.
|
||||
*
|
||||
* @param principal
|
||||
* @param credentials
|
||||
* @param authorities
|
||||
*/
|
||||
public MiniProgramAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
|
||||
super(authorities);
|
||||
this.principal = principal;
|
||||
this.credentials = credentials;
|
||||
// must use super, as we override
|
||||
super.setAuthenticated(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCredentials() {
|
||||
return this.credentials;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPrincipal() {
|
||||
return this.principal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
|
||||
if (isAuthenticated) {
|
||||
throw new IllegalArgumentException("Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
|
||||
}
|
||||
super.setAuthenticated(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eraseCredentials() {
|
||||
super.eraseCredentials();
|
||||
credentials = null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
package com.cpop.core.gateway.oam;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author DB
|
||||
* @create 2023-04-05 17:38
|
||||
* OAM管理系统为基础认证系统,使用默认的过滤认证方式
|
||||
*/
|
||||
public class OamUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
|
||||
if ("POST".equalsIgnoreCase(request.getMethod())) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
InputStream inputStream;
|
||||
Map authenticationBean;
|
||||
try {
|
||||
inputStream = request.getInputStream();
|
||||
authenticationBean = mapper.readValue(inputStream, Map.class);
|
||||
String username = (String) authenticationBean.get("username");
|
||||
String password = (String) authenticationBean.get("password");
|
||||
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
|
||||
this.setDetails(request, authRequest);
|
||||
return this.getAuthenticationManager().authenticate(authRequest);
|
||||
} catch (IOException e) {
|
||||
throw new AuthenticationServiceException("Authentication method io exception: " + request.getMethod());
|
||||
}
|
||||
}
|
||||
// 只能是post请求
|
||||
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.cpop.core.handler;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.cpop.core.base.R;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* @author: DB
|
||||
* @date: 2022-09-25 16:55
|
||||
* @Description: 无权限访问处理器
|
||||
*/
|
||||
@Component
|
||||
public class JwtAccessDeniedHandler implements AccessDeniedHandler {
|
||||
|
||||
@Override
|
||||
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException {
|
||||
httpServletResponse.setContentType("application/json;charset=UTF-8");
|
||||
httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
||||
ServletOutputStream outputStream = httpServletResponse.getOutputStream();
|
||||
R<String> result = R.fail(e.getMessage());
|
||||
outputStream.write(JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8));
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.cpop.core.handler;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.cpop.core.base.R;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* @author: DB
|
||||
* @date: 2022-09-25 16:40
|
||||
* @Description: jwt认证失败处理器
|
||||
*/
|
||||
@Component
|
||||
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||
|
||||
@Override
|
||||
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException {
|
||||
httpServletResponse.setContentType("application/json;charset=UTF-8");
|
||||
httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
ServletOutputStream outputStream = httpServletResponse.getOutputStream();
|
||||
R<String> result = R.fail("请先登录");
|
||||
outputStream.write(JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8));
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package com.cpop.core.handler;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.cpop.common.constant.Constants;
|
||||
import com.cpop.core.base.R;
|
||||
import com.cpop.core.base.entity.LoginUser;
|
||||
import com.cpop.core.base.enums.OperationLogEnum;
|
||||
import com.cpop.core.base.enums.UserType;
|
||||
import com.cpop.core.service.CoreService;
|
||||
import com.cpop.core.service.RedisService;
|
||||
import com.cpop.core.utils.JwtUtils;
|
||||
import com.cpop.core.utils.MessageUtils;
|
||||
import com.cpop.core.utils.SpringUtils;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jws;
|
||||
import io.jsonwebtoken.JwtException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
||||
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* @author: DB
|
||||
* @date: 2022-09-25 16:56
|
||||
* @Description: 登出成功处理器
|
||||
*/
|
||||
@Component
|
||||
public class JwtLogoutSuccessHandler implements LogoutSuccessHandler {
|
||||
@Autowired
|
||||
private JwtUtils jwtUtils;
|
||||
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
|
||||
@Override
|
||||
public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException {
|
||||
if (authentication != null) {
|
||||
new SecurityContextLogoutHandler().logout(httpServletRequest, httpServletResponse, authentication);
|
||||
}
|
||||
String jwt = httpServletRequest.getHeader(jwtUtils.getHeader());
|
||||
//添加退出登录成功日志
|
||||
Jws<Claims> jws = jwtUtils.getClaimsByToken(jwt);
|
||||
Claims claim = jws.getBody();
|
||||
if (claim == null) {
|
||||
throw new JwtException("token 异常");
|
||||
}
|
||||
if (jwtUtils.isTokenExpired(claim)) {
|
||||
throw new JwtException("token 已过期");
|
||||
}
|
||||
String username = claim.getSubject();
|
||||
UserType userType = UserType.valueOf(jws.getHeader().get(Constants.USER_TYPE).toString());
|
||||
//从缓存中获取
|
||||
JSONObject jsonObject = redisService.getCacheObject(userType.getKey() + username);
|
||||
if (null != jsonObject) {
|
||||
LoginUser loginUser = jsonObject.toJavaObject(LoginUser.class);
|
||||
SpringUtils.getBean(CoreService.class).insertOperationLog(Constants.SUCCESS, OperationLogEnum.SYSTEM_LOGOUT, loginUser, MessageUtils.message("i18n_operationLog_systemLogout"));
|
||||
}
|
||||
//清除缓存
|
||||
redisService.deleteObject(userType.getKey() + username);
|
||||
httpServletResponse.setContentType("application/json;charset=UTF-8");
|
||||
ServletOutputStream outputStream = httpServletResponse.getOutputStream();
|
||||
String header = jwtUtils.getHeader();
|
||||
httpServletResponse.setHeader(header, "");
|
||||
R<String> result = R.ok(MessageUtils.message("i18n_loginOut_success"));
|
||||
outputStream.write(JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8));
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
package com.cpop.core.handler;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.cpop.common.constant.Constants;
|
||||
import com.cpop.common.utils.ip.IpUtils;
|
||||
import com.cpop.core.base.R;
|
||||
import com.cpop.core.base.entity.LoginForm;
|
||||
import com.cpop.core.base.entity.LoginUser;
|
||||
import com.cpop.core.base.enums.OperationLogEnum;
|
||||
import com.cpop.core.base.enums.UserType;
|
||||
import com.cpop.core.base.exception.CpopAuthenticationException;
|
||||
import com.cpop.core.service.CoreService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author: DB
|
||||
* @date: 2022-09-25 16:24
|
||||
* @Description: 登录失败handler
|
||||
*/
|
||||
@Component
|
||||
public class LoginFailureHandler implements AuthenticationFailureHandler {
|
||||
|
||||
@Autowired
|
||||
private CoreService coreService;
|
||||
|
||||
@Override
|
||||
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException {
|
||||
httpServletResponse.setContentType("application/json;charset=UTF-8");
|
||||
ServletOutputStream outputStream = httpServletResponse.getOutputStream();
|
||||
String jsonString = httpServletRequest.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
|
||||
//映射登录表单
|
||||
LoginForm loginFormBo = JSONObject.parseObject(jsonString, LoginForm.class);
|
||||
//构建用户信息
|
||||
LoginUser loginUser = new LoginUser();
|
||||
loginUser.setUserName(loginFormBo.getUsername())
|
||||
.setIpAddr(IpUtils.getIpAddr(httpServletRequest));
|
||||
String errorMessage = "用户名或密码错误";
|
||||
R<String> result;
|
||||
//自定义认证异常,可以从这里获取到想要的参数
|
||||
if(e instanceof CpopAuthenticationException) {
|
||||
loginUser.setUserType((UserType) ((CpopAuthenticationException) e).getParams());
|
||||
errorMessage = e.getMessage();
|
||||
}
|
||||
result = R.fail(errorMessage);
|
||||
if (loginUser.getUserType() == UserType.OAM_USER) {
|
||||
//添加登录失败日志
|
||||
coreService.insertOperationLog(Constants.FAIL, OperationLogEnum.SYSTEM_LOGIN, loginUser, errorMessage);
|
||||
}
|
||||
outputStream.write(JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8));
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
package com.cpop.core.handler;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.cpop.common.constant.Constants;
|
||||
import com.cpop.common.utils.ip.IpUtils;
|
||||
import com.cpop.core.base.R;
|
||||
import com.cpop.core.base.entity.LoginSuccess;
|
||||
import com.cpop.core.base.entity.LoginUser;
|
||||
import com.cpop.core.base.enums.OperationLogEnum;
|
||||
import com.cpop.core.service.CoreService;
|
||||
import com.cpop.core.service.RedisService;
|
||||
import com.cpop.core.utils.JwtUtils;
|
||||
import com.cpop.core.utils.MessageUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* @author: DB
|
||||
* @date: 2022-09-25 16:19
|
||||
* @Description: 登录成功handler
|
||||
*/
|
||||
@Component
|
||||
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
|
||||
|
||||
@Autowired
|
||||
private JwtUtils jwtUtils;
|
||||
|
||||
@Autowired
|
||||
private CoreService coreService;
|
||||
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException{
|
||||
httpServletResponse.setContentType("application/json;charset=UTF-8");
|
||||
ServletOutputStream outputStream = httpServletResponse.getOutputStream();
|
||||
LoginSuccess loginSuccessVo = new LoginSuccess();
|
||||
LoginUser loginUser;
|
||||
if (null != authentication.getPrincipal()) {
|
||||
loginUser = (LoginUser) authentication.getPrincipal();
|
||||
} else {
|
||||
loginUser = (LoginUser) authentication.getDetails();
|
||||
}
|
||||
// 生成JWT,并放置到请求头中
|
||||
String jwt = jwtUtils.generateToken(authentication.getName(), loginUser.getUserType());
|
||||
loginSuccessVo.setToken(jwt).setUserId(loginUser.getUserId()).setRole(loginUser.getPermissions());
|
||||
String ipAddr = IpUtils.getIpAddr(httpServletRequest);
|
||||
loginUser.setIpAddr(ipAddr);
|
||||
//多种登陆方式
|
||||
multipleLogin(loginUser);
|
||||
R<LoginSuccess> result = R.ok(loginSuccessVo, MessageUtils.message("i18n_login_success"));
|
||||
outputStream.write(JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8));
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description: 多种登陆方式
|
||||
* @param loginUser 登陆用户
|
||||
* @author DB
|
||||
* @Date: 2023/8/24 0024 17:12
|
||||
*/
|
||||
private void multipleLogin(LoginUser loginUser){
|
||||
switch (loginUser.getUserType()) {
|
||||
case OAM_USER:
|
||||
//更新登录地址
|
||||
coreService.updateSysUserLoginIp(loginUser.getIpAddr(), loginUser.getUsername());
|
||||
//添加登录成功日志
|
||||
coreService.insertOperationLog(Constants.SUCCESS, OperationLogEnum.SYSTEM_LOGIN, loginUser, MessageUtils.message("i18n_login_success"));
|
||||
//将登录成功用户存入缓存
|
||||
redisService.setCacheObject(loginUser.getUserType().getKey() + loginUser.getUsername(), loginUser);
|
||||
break;
|
||||
case MINI_USER:
|
||||
//将登录成功用户存入缓存
|
||||
redisService.setCacheObject(loginUser.getUserType().getKey() + loginUser.getUsername(), loginUser);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package com.cpop.core.service.impl;
|
||||
|
||||
import com.cpop.common.constant.Constants;
|
||||
import com.cpop.common.utils.StringUtils;
|
||||
import com.cpop.core.base.entity.LoginUser;
|
||||
import com.cpop.core.utils.SecurityUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author: DB
|
||||
* @date: 2022-10-20 15:15
|
||||
* @Description:
|
||||
* AuthorityPermissionService:自定义access表达式,鉴权验证。
|
||||
* 可以将自定义的access添加到配置类中:http.anyRequest.access(aps.hasPermission(xxx,xxx));
|
||||
* 也可以直接使用注解@PreAuthorize:@PreAuthorize(aps.hasPermission(xxx));
|
||||
*/
|
||||
@Service("aps")
|
||||
public class AuthorityPermissionService {
|
||||
|
||||
public boolean hasPermission(String permissions) {
|
||||
if (StringUtils.isEmpty(permissions)) {
|
||||
return false;
|
||||
}
|
||||
// 用户信息对象
|
||||
LoginUser loginUser = SecurityUtils.getInstance().getLoginUser();
|
||||
if (loginUser == null || CollectionUtils.isEmpty(loginUser.getPermissions())) {
|
||||
return false;
|
||||
}
|
||||
Set<String> authorities = loginUser.getPermissions();
|
||||
return StringUtils.isNotEmpty(permissions) && hasPermissions(authorities, permissions);
|
||||
}
|
||||
|
||||
private boolean hasPermissions(Set<String> authorities, String permission) {
|
||||
return authorities.contains(Constants.ALL_PERMISSION) || authorities.contains(permission.trim());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
package com.cpop.core.service.impl;
|
||||
|
||||
import com.cpop.common.constant.Constants;
|
||||
import com.cpop.common.utils.bean.BeanUtils;
|
||||
import com.cpop.core.base.entity.LoginUser;
|
||||
import com.cpop.core.base.entity.loginInfo.OamStaffLoginInfo;
|
||||
import com.cpop.core.base.enums.UserType;
|
||||
import com.cpop.core.base.table.SysUser;
|
||||
import com.cpop.core.service.CoreService;
|
||||
import com.cpop.core.utils.MessageUtils;
|
||||
import com.mybatisflex.core.row.DbChain;
|
||||
import com.mybatisflex.core.row.Row;
|
||||
import com.mybatisflex.core.row.RowUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author DB
|
||||
* @createTime 2023/09/11 10:56
|
||||
* @description oam员工登陆信息
|
||||
*/
|
||||
@Service("oamStaffDetailsService")
|
||||
public class OamStaffDetailsServiceImpl implements UserDetailsService {
|
||||
|
||||
@Autowired
|
||||
private CoreService coreService;
|
||||
|
||||
/**
|
||||
* @descriptions 加载员工信息
|
||||
* @author DB
|
||||
* @date 2023/09/11 10:57
|
||||
* @param username 用户名
|
||||
* @return org.springframework.security.core.userdetails.UserDetails
|
||||
*/
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
//统一获取系统用户信息
|
||||
SysUser sysUser = coreService.getSysUser(username, UserType.OAM_USER);
|
||||
if (sysUser == null) {
|
||||
throw new UsernameNotFoundException(MessageUtils.message("i18n_alert_accountOrPwdError"));
|
||||
}
|
||||
//构建登陆员工信息
|
||||
OamStaffLoginInfo staffLoginInfo = BeanUtils.mapToClass(sysUser, OamStaffLoginInfo.class);
|
||||
staffLoginInfo.setUserId(sysUser.getId());
|
||||
//员工
|
||||
if (!staffLoginInfo.getUserName().equals(Constants.SUPER_ADMIN)) {
|
||||
Row row = DbChain.table("pp_oam_staff")
|
||||
.select()
|
||||
.where("user_id = ?", staffLoginInfo.getUserId())
|
||||
.one();
|
||||
staffLoginInfo.setDeptId(row.getString("deptId"));
|
||||
staffLoginInfo.setRoleId(row.getString("roleId"));
|
||||
staffLoginInfo.setName(row.getString("name"));
|
||||
staffLoginInfo.setStaffType(row.getInt("staffType"));
|
||||
staffLoginInfo.setId(row.getString("id"));
|
||||
}
|
||||
//获取权限
|
||||
Set<String> permissionSet = new HashSet<>();
|
||||
if (Constants.SUPER_ADMIN.equals(username)) {
|
||||
permissionSet.add(Constants.ALL_PERMISSION);
|
||||
staffLoginInfo.setName(Constants.SUPER_ADMIN);
|
||||
}
|
||||
else {
|
||||
//查询员工信息
|
||||
List<Row> list = DbChain.table("oam_menu")
|
||||
.select("pom.permission")
|
||||
.from("pp_oam_menu").as("pom")
|
||||
.leftJoin("pp_oam_role_menu").as("porm").on("porm.menu_id = pom.id")
|
||||
.where("pom.type in (1,2)")
|
||||
.and("porm.role_id = ?", staffLoginInfo.getRoleId())
|
||||
.and("pom.permission is not null")
|
||||
.list();
|
||||
if (list.isEmpty()) {
|
||||
permissionSet = new HashSet<>();
|
||||
} else {
|
||||
List<Permission> permissions = RowUtil.toEntityList(list, Permission.class);
|
||||
permissionSet = permissions.stream().map(Permission::getPermission).collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
LoginUser loginUser = new LoginUser(sysUser.getId(), staffLoginInfo, permissionSet);
|
||||
loginUser.setUserName(username)
|
||||
.setLoginTime(System.currentTimeMillis())
|
||||
.setStatus(sysUser.getStatus());
|
||||
return loginUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部自用类
|
||||
*/
|
||||
public class Permission {
|
||||
|
||||
/**
|
||||
* 权限
|
||||
*/
|
||||
private String permission;
|
||||
|
||||
public String getPermission() {
|
||||
return permission;
|
||||
}
|
||||
|
||||
public void setPermission(String permission) {
|
||||
this.permission = permission;
|
||||
}
|
||||
}
|
||||
}
|
||||
90
Cpop-Core/src/main/java/com/cpop/core/utils/JwtUtils.java
Normal file
90
Cpop-Core/src/main/java/com/cpop/core/utils/JwtUtils.java
Normal file
@ -0,0 +1,90 @@
|
||||
package com.cpop.core.utils;
|
||||
|
||||
import com.cpop.common.constant.Constants;
|
||||
import com.cpop.core.base.enums.UserType;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jws;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author: DB
|
||||
* @date: 2022-09-25 16:14
|
||||
* @Description: jwt核心工具类
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "cpop.jwt")
|
||||
public class JwtUtils {
|
||||
|
||||
/**
|
||||
* 过期时间
|
||||
*/
|
||||
private Long expire;
|
||||
/**
|
||||
* 密钥
|
||||
*/
|
||||
private String secret;
|
||||
/**
|
||||
* 请求头
|
||||
*/
|
||||
private String header;
|
||||
|
||||
/**
|
||||
* 白名单
|
||||
*/
|
||||
private String whiteList;
|
||||
|
||||
/**
|
||||
* @author LOST.yuan
|
||||
* @description 生成JWT
|
||||
* @date 16:15 2022/9/25
|
||||
* @param username 用户名
|
||||
* @return {@link String}
|
||||
**/
|
||||
public String generateToken(String username, UserType userType) {
|
||||
Date nowDate = new Date();
|
||||
Date expireDate = new Date(nowDate.getTime() + 1000 * expire);
|
||||
return Jwts.builder()
|
||||
.setHeaderParam(Constants.USER_TYPE, userType)
|
||||
.setSubject(username)
|
||||
.setIssuedAt(nowDate)
|
||||
// 7天过期
|
||||
.setExpiration(expireDate)
|
||||
.signWith(SignatureAlgorithm.HS512, secret)
|
||||
.compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* @author LOST.yuan
|
||||
* @description 解析JWT
|
||||
* @date 16:15 2022/9/25
|
||||
* @param jwt
|
||||
* @return {@link Claims}
|
||||
**/
|
||||
public Jws<Claims> getClaimsByToken(String jwt) {
|
||||
try {
|
||||
return Jwts.parser()
|
||||
.setSigningKey(secret)
|
||||
.parseClaimsJws(jwt);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author LOST.yuan
|
||||
* @description 判断JWT是否过期
|
||||
* @date 16:15 2022/9/25
|
||||
* @param claims jwt令牌
|
||||
* @return {@link boolean}
|
||||
**/
|
||||
public boolean isTokenExpired(Claims claims) {
|
||||
return claims.getExpiration().before(new Date());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package com.cpop.core.utils;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.crypto.bcrypt.BCrypt;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
|
||||
/**
|
||||
* @author: DB
|
||||
* @date: 2022-09-25 17:01
|
||||
* @Description:
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
public class PasswordEncoder extends BCryptPasswordEncoder {
|
||||
|
||||
@Autowired
|
||||
private RsaUtils rsaUtils;
|
||||
|
||||
@Override
|
||||
public boolean matches(CharSequence rawPassword, String encodedPassword) {
|
||||
// 接收到的前端的密码
|
||||
String pwd = rawPassword.toString();
|
||||
//针对+变空格进行处理
|
||||
pwd = pwd.replace(" ", "+");
|
||||
// 进行rsa解密
|
||||
try {
|
||||
pwd = rsaUtils.decrypt(pwd);
|
||||
} catch (Exception e) {
|
||||
throw new BadCredentialsException(e.getMessage());
|
||||
}
|
||||
if (encodedPassword != null && encodedPassword.length() != 0) {
|
||||
return BCrypt.checkpw(pwd, encodedPassword);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
203
Cpop-Core/src/main/java/com/cpop/core/utils/RsaUtils.java
Normal file
203
Cpop-Core/src/main/java/com/cpop/core/utils/RsaUtils.java
Normal file
@ -0,0 +1,203 @@
|
||||
package com.cpop.core.utils;
|
||||
|
||||
import com.cpop.core.base.exception.UtilException;
|
||||
import com.cpop.core.config.GenerateKeyPairConfig;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.*;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author DB
|
||||
* @Description: Rsa相关工具类
|
||||
* @create 2023-08-04 23:09
|
||||
*/
|
||||
@Component
|
||||
public class RsaUtils {
|
||||
|
||||
@Autowired
|
||||
private GenerateKeyPairConfig keyPairConfig;
|
||||
|
||||
// region 私有方法
|
||||
|
||||
/**
|
||||
* 生成密钥对
|
||||
* @return 返回map集合,其中包含publicKey与privateKey
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
private Map<String, Key> generateKeyPair() throws NoSuchAlgorithmException {
|
||||
//RSA算法要求有一个可信任的随机数源
|
||||
SecureRandom secureRandom = new SecureRandom();
|
||||
//为RSA算法创建一个KeyPairGenerator对象
|
||||
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(keyPairConfig.getAlgorithm());
|
||||
//利用上面的随机数据源初始化这个KeyPairGenerator对象
|
||||
keyPairGenerator.initialize(keyPairConfig.getKeySize(), secureRandom);
|
||||
//生成密匙对
|
||||
KeyPair keyPair = keyPairGenerator.generateKeyPair();
|
||||
//得到公钥
|
||||
Key publicKey = keyPair.getPublic();
|
||||
//得到私钥
|
||||
Key privateKey = keyPair.getPrivate();
|
||||
Map<String, Key> keyPairMap = new HashMap<>();
|
||||
keyPairMap.put("publicKey", publicKey);
|
||||
keyPairMap.put("privateKey", privateKey);
|
||||
return keyPairMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件中获取密钥对象
|
||||
* @param fileName 文件名
|
||||
* @return 密钥对象
|
||||
*/
|
||||
private Key getKeyFromFile(String fileName) {
|
||||
Key key = null;
|
||||
ObjectInputStream ois = null;
|
||||
try {
|
||||
ois = new ObjectInputStream(Files.newInputStream(Paths.get(fileName)));
|
||||
key = (Key) ois.readObject();
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
throw new UtilException(e.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
assert ois != null;
|
||||
ois.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将密钥对生成到文件中
|
||||
*/
|
||||
private void generateKeyPairToFiles() {
|
||||
ObjectOutputStream oosPublicKey = null;
|
||||
ObjectOutputStream oosPrivateKey = null;
|
||||
try {
|
||||
Map<String, Key> keyPairMap = generateKeyPair();
|
||||
Key publicKey = keyPairMap.get("publicKey");
|
||||
Key privateKey = keyPairMap.get("privateKey");
|
||||
oosPublicKey = new ObjectOutputStream(Files.newOutputStream(Paths.get(keyPairConfig.getPublicKeyFile())));
|
||||
oosPrivateKey = new ObjectOutputStream(Files.newOutputStream(Paths.get(keyPairConfig.getPrivateKeyFile())));
|
||||
oosPublicKey.writeObject(publicKey);
|
||||
oosPrivateKey.writeObject(privateKey);
|
||||
} catch (NoSuchAlgorithmException | IOException e) {
|
||||
throw new UtilException(e.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
//清空缓存,关闭文件输出流
|
||||
assert oosPublicKey != null;
|
||||
oosPublicKey.close();
|
||||
assert oosPrivateKey != null;
|
||||
oosPrivateKey.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化密钥对文件
|
||||
* @return 返回密钥对信息【publicKey(公钥字符串)、、privateKey(私钥字符串)】
|
||||
*/
|
||||
public Map<String, String> initKeyPair() {
|
||||
Map<String, String> keyPairMap = new HashMap<>();
|
||||
File publicFile = new File(keyPairConfig.getPublicKeyFile());
|
||||
File privateFile = new File(keyPairConfig.getPrivateKeyFile());
|
||||
//判断是否存在公钥和私钥文件
|
||||
if (!publicFile.exists() || !privateFile.exists()) {
|
||||
generateKeyPairToFiles();
|
||||
}
|
||||
ObjectInputStream oisPublic = null;
|
||||
ObjectInputStream oisPrivate = null;
|
||||
Key publicKey = null;
|
||||
Key privateKey = null;
|
||||
try {
|
||||
oisPublic = new ObjectInputStream(Files.newInputStream(Paths.get(keyPairConfig.getPublicKeyFile())));
|
||||
oisPrivate = new ObjectInputStream(Files.newInputStream(Paths.get(keyPairConfig.getPrivateKeyFile())));
|
||||
publicKey = (Key) oisPublic.readObject();
|
||||
privateKey = (Key) oisPrivate.readObject();
|
||||
byte[] publicKeyBytes = publicKey.getEncoded();
|
||||
byte[] privateKeyBytes = privateKey.getEncoded();
|
||||
String publicKeyBase64 = Base64.getEncoder().encodeToString(publicKeyBytes);
|
||||
String privateKeyBase64 = Base64.getEncoder().encodeToString(privateKeyBytes);
|
||||
//公钥字符串
|
||||
keyPairMap.put("publicKey", publicKeyBase64);
|
||||
//私钥字符串
|
||||
keyPairMap.put("privateKey", privateKeyBase64);
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
throw new UtilException(e.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
assert oisPrivate != null;
|
||||
oisPrivate.close();
|
||||
oisPublic.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return keyPairMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密方法
|
||||
* @param source 源数据
|
||||
* @return 加密后的字符串
|
||||
*/
|
||||
public String encrypt(String source) {
|
||||
Key publicKey = getKeyFromFile(keyPairConfig.getPublicKeyFile());
|
||||
Base64.Encoder encoder = Base64.getEncoder();
|
||||
String encryptSource = null;
|
||||
try {
|
||||
//得到Cipher对象来实现对源数据的RSA加密
|
||||
Cipher cipher = Cipher.getInstance(keyPairConfig.getAlgorithm());
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
byte[] bytes = source.getBytes();
|
||||
//执行加密操作
|
||||
encryptSource = encoder.encodeToString(cipher.doFinal(bytes));
|
||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException |
|
||||
BadPaddingException e) {
|
||||
throw new UtilException(e.getMessage());
|
||||
}
|
||||
return encryptSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密方法
|
||||
* @param source 密文
|
||||
* @return 解密后的字符串
|
||||
*/
|
||||
public String decrypt(String source) {
|
||||
Key privateKey = getKeyFromFile(keyPairConfig.getPrivateKeyFile());
|
||||
Base64.Decoder decoder = Base64.getDecoder();
|
||||
String decryptSource = null;
|
||||
try {
|
||||
//得到Cipher对象对已用公钥加密的数据进行RSA解密
|
||||
Cipher cipher = Cipher.getInstance(keyPairConfig.getAlgorithm());
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
//执行解密操作
|
||||
byte[] bytes = decoder.decode(source);
|
||||
decryptSource = new String(cipher.doFinal(bytes), StandardCharsets.UTF_8);
|
||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException |
|
||||
IllegalBlockSizeException | BadPaddingException e) {
|
||||
throw new UtilException(e.getMessage());
|
||||
}
|
||||
return decryptSource;
|
||||
}
|
||||
|
||||
}
|
||||
20
pom.xml
20
pom.xml
@ -30,6 +30,8 @@
|
||||
<fastjson.version>2.0.38</fastjson.version>
|
||||
<mybatis-flex.version>1.6.4</mybatis-flex.version>
|
||||
<easyexcel.version>3.3.2</easyexcel.version>
|
||||
<commons-compress.version>1.21</commons-compress.version>
|
||||
<jjwt.version>0.9.1</jjwt.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
@ -58,12 +60,24 @@
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
<!-- jwt 相关依赖-->
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
</dependency>
|
||||
<!--Cpop公共包-->
|
||||
<dependency>
|
||||
<groupId>com.cpop</groupId>
|
||||
<artifactId>Cpop-Common</artifactId>
|
||||
<version>${cpop.version}</version>
|
||||
</dependency>
|
||||
<!--Cpop公共包-->
|
||||
<dependency>
|
||||
<groupId>com.cpop</groupId>
|
||||
<artifactId>Cpop-Core</artifactId>
|
||||
<version>${cpop.version}</version>
|
||||
</dependency>
|
||||
<!--Mybatis-flex-->
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
@ -81,6 +95,12 @@
|
||||
<artifactId>easyexcel</artifactId>
|
||||
<version>${easyexcel.version}</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-compress -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>${commons-compress.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user