Compare commits
12 Commits
0e29f348e5
...
3204c89d6e
| Author | SHA1 | Date | |
|---|---|---|---|
| 3204c89d6e | |||
| a21f6803f9 | |||
| 4d8f27a991 | |||
| e34b326d9f | |||
| 4229247f77 | |||
| 3e05e32d4b | |||
| 31fb0398bb | |||
| 29b449dbb3 | |||
| 16d334f217 | |||
| 23d2353b07 | |||
| 7dc8fac2cf | |||
| cc4ef5e62c |
33
.gitignore
vendored
Normal file
33
.gitignore
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
/logs/
|
||||
/.idea/
|
||||
/Auth/target/
|
||||
/Auth/Auth.iml
|
||||
/Common/Common.iml
|
||||
/Common/target/
|
||||
/Dependencies/Dependencies.iml
|
||||
/Dependencies/target/
|
||||
/Feign/Feign.iml
|
||||
/Feign/target/
|
||||
/Gateway/Gateway.iml
|
||||
/Gateway/target/
|
||||
/LicenseAnalysis/LicenseAnalysis.iml
|
||||
/LicenseAnalysis/target/
|
||||
/MessageCenter/MessageCenter.iml
|
||||
/MessageCenter/target/
|
||||
/ResourceManager/ResourceManager.iml
|
||||
/ResourceManager/target/
|
||||
/WXEngine/WXEngine.iml
|
||||
/WXEngine/target/
|
||||
/Auth/src/main/resources/application-test.yml
|
||||
/Auth/src/main/resources/bootstrap-test.yml
|
||||
/Feign/src/main/resources/application-test.yml
|
||||
/Feign/src/main/resources/bootstrap-test.yml
|
||||
/Gateway/src/main/resources/application-test.yml
|
||||
/ResourceManager/src/main/resources/application-test.yml
|
||||
/ResourceManager/src/main/resources/bootstrap-test.yml
|
||||
/WXEngine/src/main/resources/bootstrap-test.yml
|
||||
/WXEngine/src/main/resources/application-test.yml
|
||||
/General/src/main/resources/application-test.yml
|
||||
/General/src/main/resources/bootstrap-test.yml
|
||||
/General/General.iml
|
||||
/General/target/
|
||||
153
Auth/pom.xml
Normal file
153
Auth/pom.xml
Normal file
@ -0,0 +1,153 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
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>cn.crtech.cloud.auth</groupId>
|
||||
<artifactId>Auth</artifactId>
|
||||
<version>1.0.1</version>
|
||||
|
||||
<!-- 父工程 -->
|
||||
<parent>
|
||||
<groupId>cn.crtech.cloud.dependencies</groupId>
|
||||
<artifactId>Dependencies</artifactId>
|
||||
<version>1.0.1</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<!-- 依赖的版本锁定 -->
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<java.version>1.8</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
|
||||
<nimbus.jwt.version>9.14</nimbus.jwt.version>
|
||||
<oauth2.version>2.2.5.RELEASE</oauth2.version>
|
||||
<cn.crtech.cloud.common>1.0.1</cn.crtech.cloud.common>
|
||||
|
||||
<weixin-java-miniapp.version>4.4.0</weixin-java-miniapp.version>
|
||||
<weixin.mp.version>4.3.0</weixin.mp.version>
|
||||
<tencentcloud.sdk.version>3.1.322</tencentcloud.sdk.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- springboot-framework -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.lettuce</groupId>
|
||||
<artifactId>lettuce-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- spring-alibaba-cloud-client -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<groupId>commons-io</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- jwt -->
|
||||
<dependency>
|
||||
<groupId>com.nimbusds</groupId>
|
||||
<artifactId>nimbus-jose-jwt</artifactId>
|
||||
<version>${nimbus.jwt.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- oauth2 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-oauth2</artifactId>
|
||||
<version>${oauth2.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>bcpkix-jdk15on</artifactId>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- 自定义共有内容仓库 -->
|
||||
<dependency>
|
||||
<groupId>cn.crtech.cloud.common</groupId>
|
||||
<artifactId>Common</artifactId>
|
||||
<version>${cn.crtech.cloud.common}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- jedis -->
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 微信小程序JDK工具包 -->
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-miniapp</artifactId>
|
||||
<version>${weixin-java-miniapp.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>guava</artifactId>
|
||||
<groupId>com.google.guava</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- 微信公众号JDK工具包 -->
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-mp</artifactId>
|
||||
<version>${weixin.mp.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>weixin-java-common</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- 腾讯云sdk -->
|
||||
<dependency>
|
||||
<groupId>com.tencentcloudapi</groupId>
|
||||
<artifactId>tencentcloud-sdk-java</artifactId>
|
||||
<version>${tencentcloud.sdk.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>okio</artifactId>
|
||||
<groupId>com.squareup.okio</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
36
Auth/src/main/java/cn/crtech/cloud/auth/AuthApplication.java
Normal file
36
Auth/src/main/java/cn/crtech/cloud/auth/AuthApplication.java
Normal file
@ -0,0 +1,36 @@
|
||||
package cn.crtech.cloud.auth;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import tk.mybatis.spring.annotation.MapperScan;
|
||||
|
||||
/**
|
||||
* Author : yj
|
||||
* Date : 2021-01-13
|
||||
* Description:
|
||||
*/
|
||||
|
||||
//微服务启动时使用 begin
|
||||
@SpringBootApplication
|
||||
@EnableDiscoveryClient
|
||||
@MapperScan("cn.crtech.cloud.auth.mapper")
|
||||
public class AuthApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(AuthApplication.class, args);
|
||||
}
|
||||
}
|
||||
//微服务启动时使用 end
|
||||
|
||||
//使用launcher启动时使用 begin
|
||||
//launcher.NacosConfig @Component需要放开
|
||||
|
||||
//@SpringBootApplication
|
||||
//public class AuthApplication extends SpringBootServletInitializer {
|
||||
// @Override
|
||||
// protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
// return application.sources(AuthApplication.class);
|
||||
// }
|
||||
//}
|
||||
|
||||
//使用launcher启动时使用 end
|
||||
@ -0,0 +1,36 @@
|
||||
package cn.crtech.cloud.auth.component;
|
||||
|
||||
import cn.crtech.cloud.auth.pojo.SecurityUser;
|
||||
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
||||
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* JWT内容增强器
|
||||
* token信息的额外信息处理
|
||||
*/
|
||||
@Component
|
||||
public class JwtTokenEnhancer implements TokenEnhancer {
|
||||
@Override
|
||||
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
|
||||
SecurityUser securityUser = (SecurityUser) authentication.getPrincipal();
|
||||
Map<String, Object> info = new HashMap<>();
|
||||
//把用户ID设置到JWT中
|
||||
info.put("id", securityUser.getId());
|
||||
info.put("company_code", securityUser.getCompanyCode());
|
||||
info.put("company_name", securityUser.getCompanyName());
|
||||
info.put("mobile", securityUser.getMobile());
|
||||
info.put("nick_name", securityUser.getNickName());
|
||||
info.put("email", securityUser.getEmail());
|
||||
info.put("company_admin", securityUser.getIsCompanyAdmin());
|
||||
info.put("data_source", securityUser.getDataSource());
|
||||
info.put("data_source_id", securityUser.getDataSourceId());
|
||||
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(info);
|
||||
return accessToken;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package cn.crtech.cloud.auth.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 跨域拦截器,用于401处理
|
||||
* <p>
|
||||
* Author : yj
|
||||
* Date : 2021-03-11
|
||||
* Description:
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
public class CrossInterceptor implements HandlerInterceptor {
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||
String origin = request.getHeader(HttpHeaders.ORIGIN);
|
||||
if (origin != null) {
|
||||
response.setHeader("Access-Control-Allow-Origin", origin);
|
||||
response.setHeader("Access-Control-Allow-Credentials", "true");
|
||||
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT, HEAD");
|
||||
response.setHeader("Access-Control-Allow-Headers", "Content-Type, X-Access-Token");
|
||||
response.setHeader("Access-Control-Max-Age", "3600");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,176 @@
|
||||
package cn.crtech.cloud.auth.config;
|
||||
|
||||
import cn.crtech.cloud.auth.component.JwtTokenEnhancer;
|
||||
import cn.crtech.cloud.auth.mapper.AuthorizeMapper;
|
||||
import cn.crtech.cloud.auth.pojo.MisApp;
|
||||
import cn.crtech.cloud.auth.service.system.AuthService;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.oauth2.config.annotation.builders.ClientDetailsServiceBuilder;
|
||||
import org.springframework.security.oauth2.config.annotation.builders.InMemoryClientDetailsServiceBuilder;
|
||||
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
|
||||
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
|
||||
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
|
||||
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
|
||||
import org.springframework.security.rsa.crypto.KeyStoreKeyFactory;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
|
||||
|
||||
import java.security.KeyPair;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Oauth2认证服务器配置
|
||||
* AuthorizationServer配置的适配类
|
||||
*/
|
||||
|
||||
@AllArgsConstructor
|
||||
@Configuration
|
||||
@EnableAuthorizationServer//开启认证服务
|
||||
public class Oauth2ServerConfig extends AuthorizationServerConfigurerAdapter {
|
||||
@Autowired
|
||||
AuthorizeMapper authorizeMapper;
|
||||
|
||||
private final static int ACCESS_TOKEN_VALIDITY_SECONDS = 3600;
|
||||
private final static int REFRESH_TOKEN_VALIDITY_SECONDS = 86400;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final AuthService authService;
|
||||
private final AuthenticationManager authenticationManager;
|
||||
private final JwtTokenEnhancer jwtTokenEnhancer;
|
||||
|
||||
/**
|
||||
* 配置前端应用认证
|
||||
* 配置从哪里获取ClientDetails信息
|
||||
*
|
||||
* @param clients
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
|
||||
InMemoryClientDetailsServiceBuilder builder = clients.inMemory();
|
||||
List<MisApp> applicationList = authorizeMapper.getAll();
|
||||
|
||||
//将客户端信息存储在内存中
|
||||
applicationList.forEach(application -> {
|
||||
ClientDetailsServiceBuilder<InMemoryClientDetailsServiceBuilder>.ClientBuilder clientBuilder = builder.withClient(application.getCode())
|
||||
.secret(passwordEncoder.encode(application.getClientSecret()))
|
||||
.scopes(application.getScope())// 允许的授权范围 all
|
||||
.authorizedGrantTypes(application.getAuthorizedGrantTypes().split(",")) //"password", "refresh_token"
|
||||
.accessTokenValiditySeconds(application.getAccessTokenValidity() == null ? ACCESS_TOKEN_VALIDITY_SECONDS : application.getAccessTokenValidity())
|
||||
.refreshTokenValiditySeconds(application.getRefreshTokenValidity() == null ? REFRESH_TOKEN_VALIDITY_SECONDS : application.getRefreshTokenValidity());
|
||||
if (!StrUtil.isEmpty(application.getWebServerRedirectUri())) {
|
||||
clientBuilder.redirectUris(application.getWebServerRedirectUri());
|
||||
}
|
||||
if (!StrUtil.isEmpty(application.getResourceIds())) {
|
||||
clientBuilder.resourceIds(application.getResourceIds());
|
||||
}
|
||||
if (!StrUtil.isEmpty(application.getAuthorities())) {
|
||||
clientBuilder.authorities(application.getAuthorities());
|
||||
}
|
||||
if (!StrUtil.isEmpty(application.getAdditionalInformation())) {
|
||||
clientBuilder.additionalInformation(application.getAdditionalInformation());
|
||||
}
|
||||
if (!StrUtil.isEmpty(application.getAutoApprove())) {
|
||||
clientBuilder.autoApprove(application.getAutoApprove());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入相关配置:
|
||||
* 1. 密码模式下配置认证管理器 AuthenticationManager
|
||||
* 2. userDetailsService注入
|
||||
*/
|
||||
@Override
|
||||
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
|
||||
TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
|
||||
List<TokenEnhancer> delegates = new ArrayList<>();
|
||||
|
||||
delegates.add(jwtTokenEnhancer);
|
||||
|
||||
delegates.add(accessTokenConverter());
|
||||
enhancerChain.setTokenEnhancers(delegates); //配置JWT的内容增强器
|
||||
|
||||
endpoints.authenticationManager(authenticationManager)
|
||||
.userDetailsService(authService) //配置加载用户信息的服务
|
||||
.accessTokenConverter(accessTokenConverter())
|
||||
.tokenEnhancer(enhancerChain)
|
||||
.tokenServices(customTokenServices(endpoints)); //配置token增强
|
||||
}
|
||||
|
||||
public UserTokenServices customTokenServices(AuthorizationServerEndpointsConfigurer endpoints) {
|
||||
UserTokenServices tokenServices = new UserTokenServices();
|
||||
tokenServices.setTokenStore(endpoints.getTokenStore());
|
||||
tokenServices.setSupportRefreshToken(true);
|
||||
tokenServices.setReuseRefreshToken(true);
|
||||
tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
|
||||
// 设置自定义的CustomUserDetailsByNameServiceWrapper
|
||||
if (authService != null) {
|
||||
PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
|
||||
provider.setPreAuthenticatedUserDetailsService(new UserByNameServiceWrapper<>(authService));
|
||||
tokenServices.setAuthenticationManager(new ProviderManager(Arrays.asList(provider)));
|
||||
}
|
||||
return tokenServices;
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置:安全检查流程,用来配置令牌端点(Token Endpoint)的安全与权限访问
|
||||
* 默认过滤器:BasicAuthenticationFilter
|
||||
* 1、oauth_client_details表中clientSecret字段加密【ClientDetails属性secret】
|
||||
* 2、CheckEndpoint类的接口 oauth/check_token 无需经过过滤器过滤,默认值:denyAll()
|
||||
* 对以下的几个端点进行权限配置:
|
||||
* /oauth/authorize:授权端点
|
||||
* /oauth/token:令牌端点
|
||||
* /oauth/confirm_access:用户确认授权提交端点
|
||||
* /oauth/error:授权服务错误信息端点
|
||||
* /oauth/check_token:用于资源服务访问的令牌解析端点
|
||||
* /oauth/token_key:提供公有密匙的端点,如果使用JWT令牌的话
|
||||
**/
|
||||
@Override
|
||||
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
|
||||
// security//客户端校验token访问许可 /oauth/check_key公开
|
||||
// .checkTokenAccess("permitAll()")
|
||||
// //客户端token调用许可 /oauth/check_token公开
|
||||
// .tokenKeyAccess("permitAll()")
|
||||
// //表单认证,申请令牌
|
||||
// .allowFormAuthenticationForClients()
|
||||
// .passwordEncoder(new BCryptPasswordEncoder());
|
||||
security.allowFormAuthenticationForClients();
|
||||
}
|
||||
|
||||
/**
|
||||
* jwttoken转换器
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public JwtAccessTokenConverter accessTokenConverter() {
|
||||
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
|
||||
jwtAccessTokenConverter.setKeyPair(keyPair());
|
||||
return jwtAccessTokenConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 采用非对称加密
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public KeyPair keyPair() {
|
||||
//从classpath下的证书中获取秘钥对
|
||||
KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("jwt.jks"), "123456".toCharArray());
|
||||
return keyStoreKeyFactory.getKeyPair("jwt", "123456".toCharArray());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package cn.crtech.cloud.auth.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
|
||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
/**
|
||||
* Redis相关配置
|
||||
*/
|
||||
@Configuration
|
||||
@EnableRedisRepositories
|
||||
public class RedisRepositoryConfig {
|
||||
@Bean
|
||||
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setConnectionFactory(connectionFactory);
|
||||
|
||||
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
|
||||
|
||||
redisTemplate.setKeySerializer(stringRedisSerializer);
|
||||
redisTemplate.setHashKeySerializer(stringRedisSerializer);
|
||||
Jackson2JsonRedisSerializer<?> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
|
||||
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
|
||||
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
|
||||
redisTemplate.afterPropertiesSet();
|
||||
return redisTemplate;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,132 @@
|
||||
package cn.crtech.cloud.auth.config;
|
||||
|
||||
import cn.crtech.cloud.auth.service.system.AuthUserService;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.InternalAuthenticationServiceException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsPasswordService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Map;
|
||||
|
||||
public class UserAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
|
||||
private static final String USER_NOT_FOUND_PASSWORD = "userNotFoundPassword";
|
||||
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
private volatile String userNotFoundEncodedPassword;
|
||||
|
||||
private UserDetailsPasswordService userDetailsPasswordService;
|
||||
|
||||
@Resource
|
||||
private AuthUserService authUserService;
|
||||
|
||||
public UserAuthenticationProvider() {
|
||||
this.setPasswordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
|
||||
if (authentication.getCredentials() == null) {
|
||||
this.logger.debug("Authentication failed: no credentials provided");
|
||||
throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
|
||||
} else {
|
||||
String presentedPassword = authentication.getCredentials().toString();
|
||||
if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
|
||||
this.logger.debug("Authentication failed: password does not match stored value");
|
||||
throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void doAfterPropertiesSet() {
|
||||
Assert.notNull(this.authUserService, "A UserDetailsService must be set");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
|
||||
this.prepareTimingAttackProtection();
|
||||
// 自定义添加
|
||||
Map<String, String> map = (Map<String, String>) authentication.getDetails();
|
||||
try {
|
||||
// 自定义添加
|
||||
UserDetails loadedUser = getAuthUserService().loadUserByUsername(username, map.get("companyCode"));
|
||||
if (loadedUser == null) {
|
||||
throw new InternalAuthenticationServiceException("UserDetailsService returned null, which is an interface contract violation");
|
||||
} else {
|
||||
return loadedUser;
|
||||
}
|
||||
} catch (UsernameNotFoundException var4) {
|
||||
this.mitigateAgainstTimingAttack(authentication);
|
||||
throw var4;
|
||||
} catch (InternalAuthenticationServiceException var5) {
|
||||
throw var5;
|
||||
} catch (Exception var6) {
|
||||
throw new InternalAuthenticationServiceException(var6.getMessage(), var6);
|
||||
}
|
||||
}
|
||||
|
||||
protected Authentication createSuccessAuthentication(Object principal, Authentication authentication, UserDetails user) {
|
||||
boolean upgradeEncoding = this.userDetailsPasswordService != null && this.passwordEncoder.upgradeEncoding(user.getPassword());
|
||||
if (upgradeEncoding) {
|
||||
String presentedPassword = authentication.getCredentials().toString();
|
||||
String newPassword = this.passwordEncoder.encode(presentedPassword);
|
||||
user = this.userDetailsPasswordService.updatePassword(user, newPassword);
|
||||
}
|
||||
|
||||
return super.createSuccessAuthentication(principal, authentication, user);
|
||||
}
|
||||
|
||||
private void prepareTimingAttackProtection() {
|
||||
if (this.userNotFoundEncodedPassword == null) {
|
||||
this.userNotFoundEncodedPassword = this.passwordEncoder.encode("userNotFoundPassword");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void mitigateAgainstTimingAttack(UsernamePasswordAuthenticationToken authentication) {
|
||||
if (authentication.getCredentials() != null) {
|
||||
String presentedPassword = authentication.getCredentials().toString();
|
||||
this.passwordEncoder.matches(presentedPassword, this.userNotFoundEncodedPassword);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
|
||||
Assert.notNull(passwordEncoder, "passwordEncoder cannot be null");
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
this.userNotFoundEncodedPassword = null;
|
||||
}
|
||||
|
||||
public String getUserNotFoundEncodedPassword() {
|
||||
return userNotFoundEncodedPassword;
|
||||
}
|
||||
|
||||
public void setUserNotFoundEncodedPassword(String userNotFoundEncodedPassword) {
|
||||
this.userNotFoundEncodedPassword = userNotFoundEncodedPassword;
|
||||
}
|
||||
|
||||
public UserDetailsPasswordService getUserDetailsPasswordService() {
|
||||
return userDetailsPasswordService;
|
||||
}
|
||||
|
||||
public void setUserDetailsPasswordService(UserDetailsPasswordService userDetailsPasswordService) {
|
||||
this.userDetailsPasswordService = userDetailsPasswordService;
|
||||
}
|
||||
|
||||
public AuthUserService getAuthUserService() {
|
||||
return authUserService;
|
||||
}
|
||||
|
||||
public void setAuthUserService(AuthUserService authUserService) {
|
||||
this.authUserService = authUserService;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package cn.crtech.cloud.auth.config;
|
||||
|
||||
import cn.crtech.cloud.auth.service.system.AuthService;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class UserByNameServiceWrapper<T extends Authentication> implements AuthenticationUserDetailsService<T>, InitializingBean {
|
||||
private AuthService authService = null;
|
||||
|
||||
public UserByNameServiceWrapper() {
|
||||
}
|
||||
|
||||
public UserByNameServiceWrapper(final AuthService authService) {
|
||||
Assert.notNull(authService, "userDetailsService cannot be null.");
|
||||
this.authService = authService;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
Assert.notNull(this.authService, "UserDetailsService must be set");
|
||||
}
|
||||
|
||||
public UserDetails loadUserDetails(T authentication) throws UsernameNotFoundException {
|
||||
// ----------添加自定义的内容----------
|
||||
AbstractAuthenticationToken principal = (AbstractAuthenticationToken) authentication.getPrincipal();
|
||||
// ----------添加自定义的内容----------
|
||||
Map<String, String> map = (Map<String, String>) principal.getDetails();
|
||||
return this.authService.loadUserByUsername(authentication.getName(), map.get("companyCode")); // 使用自定义的userDetailsService
|
||||
}
|
||||
|
||||
public void setUserDetailsService(AuthService authService) {
|
||||
this.authService = authService;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,306 @@
|
||||
package cn.crtech.cloud.auth.config;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.oauth2.common.*;
|
||||
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
|
||||
import org.springframework.security.oauth2.common.exceptions.InvalidScopeException;
|
||||
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
|
||||
import org.springframework.security.oauth2.provider.*;
|
||||
import org.springframework.security.oauth2.provider.token.*;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class UserTokenServices implements AuthorizationServerTokenServices, ResourceServerTokenServices, ConsumerTokenServices, InitializingBean {
|
||||
private int refreshTokenValiditySeconds = 2592000;
|
||||
private int accessTokenValiditySeconds = 43200;
|
||||
private boolean supportRefreshToken = false;
|
||||
private boolean reuseRefreshToken = true;
|
||||
private TokenStore tokenStore;
|
||||
private ClientDetailsService clientDetailsService;
|
||||
private TokenEnhancer accessTokenEnhancer;
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
||||
public UserTokenServices() {
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(this.tokenStore, "tokenStore must be set");
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException {
|
||||
OAuth2AccessToken existingAccessToken = this.tokenStore.getAccessToken(authentication);
|
||||
OAuth2RefreshToken refreshToken = null;
|
||||
if (existingAccessToken != null) {
|
||||
if (!existingAccessToken.isExpired()) {
|
||||
this.tokenStore.storeAccessToken(existingAccessToken, authentication);
|
||||
return existingAccessToken;
|
||||
}
|
||||
|
||||
if (existingAccessToken.getRefreshToken() != null) {
|
||||
refreshToken = existingAccessToken.getRefreshToken();
|
||||
this.tokenStore.removeRefreshToken(refreshToken);
|
||||
}
|
||||
|
||||
this.tokenStore.removeAccessToken(existingAccessToken);
|
||||
}
|
||||
|
||||
if (refreshToken == null) {
|
||||
refreshToken = this.createRefreshToken(authentication);
|
||||
} else if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
|
||||
ExpiringOAuth2RefreshToken expiring = (ExpiringOAuth2RefreshToken) refreshToken;
|
||||
if (System.currentTimeMillis() > expiring.getExpiration().getTime()) {
|
||||
refreshToken = this.createRefreshToken(authentication);
|
||||
}
|
||||
}
|
||||
|
||||
OAuth2AccessToken accessToken = this.createAccessToken(authentication, refreshToken);
|
||||
this.tokenStore.storeAccessToken(accessToken, authentication);
|
||||
refreshToken = accessToken.getRefreshToken();
|
||||
if (refreshToken != null) {
|
||||
this.tokenStore.storeRefreshToken(refreshToken, authentication);
|
||||
}
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
@Transactional(
|
||||
noRollbackFor = {InvalidTokenException.class, InvalidGrantException.class}
|
||||
)
|
||||
public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest tokenRequest) throws AuthenticationException {
|
||||
if (!this.supportRefreshToken) {
|
||||
throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue);
|
||||
} else {
|
||||
OAuth2RefreshToken refreshToken = this.tokenStore.readRefreshToken(refreshTokenValue);
|
||||
if (refreshToken == null) {
|
||||
throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue);
|
||||
} else {
|
||||
OAuth2Authentication authentication = this.tokenStore.readAuthenticationForRefreshToken(refreshToken);
|
||||
if (this.authenticationManager != null && !authentication.isClientOnly()) {
|
||||
// OAuth2Authentication 中的 Authentication userAuthentication 丢失了 Detail的信息,需要补上
|
||||
// 1.从tokenRequest中获取请求的信息,并重新构造成 UsernamePasswordAuthenticationToken
|
||||
// 2.设置好了Detail的信息再传入构造 PreAuthenticatedAuthenticationToken 交由后面的验证
|
||||
tokenRequest.getRequestParameters();
|
||||
Object details = tokenRequest.getRequestParameters();
|
||||
UsernamePasswordAuthenticationToken userAuthentication = (UsernamePasswordAuthenticationToken) authentication.getUserAuthentication();
|
||||
userAuthentication.setDetails(details);
|
||||
// 去掉原来的,使用自己重新构造的 userAuthentication
|
||||
// Authentication user = new PreAuthenticatedAuthenticationToken(authentication.getUserAuthentication(), "", authentication.getAuthorities());
|
||||
Authentication user = new PreAuthenticatedAuthenticationToken(userAuthentication, "", authentication.getAuthorities());
|
||||
user = this.authenticationManager.authenticate(user);
|
||||
authentication = new OAuth2Authentication(authentication.getOAuth2Request(), user);
|
||||
authentication.setDetails(details);
|
||||
}
|
||||
|
||||
String clientId = authentication.getOAuth2Request().getClientId();
|
||||
if (clientId != null && clientId.equals(tokenRequest.getClientId())) {
|
||||
this.tokenStore.removeAccessTokenUsingRefreshToken(refreshToken);
|
||||
if (this.isExpired(refreshToken)) {
|
||||
this.tokenStore.removeRefreshToken(refreshToken);
|
||||
throw new InvalidTokenException("Invalid refresh token (expired): " + refreshToken);
|
||||
} else {
|
||||
authentication = this.createRefreshedAuthentication(authentication, tokenRequest);
|
||||
if (!this.reuseRefreshToken) {
|
||||
this.tokenStore.removeRefreshToken(refreshToken);
|
||||
refreshToken = this.createRefreshToken(authentication);
|
||||
}
|
||||
|
||||
OAuth2AccessToken accessToken = this.createAccessToken(authentication, refreshToken);
|
||||
this.tokenStore.storeAccessToken(accessToken, authentication);
|
||||
if (!this.reuseRefreshToken) {
|
||||
this.tokenStore.storeRefreshToken(accessToken.getRefreshToken(), authentication);
|
||||
}
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
} else {
|
||||
throw new InvalidGrantException("Wrong client for this refresh token: " + refreshTokenValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {
|
||||
return this.tokenStore.getAccessToken(authentication);
|
||||
}
|
||||
|
||||
private OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication authentication, TokenRequest request) {
|
||||
Set<String> scope = request.getScope();
|
||||
OAuth2Request clientAuth = authentication.getOAuth2Request().refresh(request);
|
||||
if (scope != null && !scope.isEmpty()) {
|
||||
Set<String> originalScope = clientAuth.getScope();
|
||||
if (originalScope == null || !originalScope.containsAll(scope)) {
|
||||
throw new InvalidScopeException("Unable to narrow the scope of the client authentication to " + scope + ".", originalScope);
|
||||
}
|
||||
|
||||
clientAuth = clientAuth.narrowScope(scope);
|
||||
}
|
||||
|
||||
OAuth2Authentication narrowed = new OAuth2Authentication(clientAuth, authentication.getUserAuthentication());
|
||||
return narrowed;
|
||||
}
|
||||
|
||||
protected boolean isExpired(OAuth2RefreshToken refreshToken) {
|
||||
if (!(refreshToken instanceof ExpiringOAuth2RefreshToken)) {
|
||||
return false;
|
||||
} else {
|
||||
ExpiringOAuth2RefreshToken expiringToken = (ExpiringOAuth2RefreshToken) refreshToken;
|
||||
return expiringToken.getExpiration() == null || System.currentTimeMillis() > expiringToken.getExpiration().getTime();
|
||||
}
|
||||
}
|
||||
|
||||
public OAuth2AccessToken readAccessToken(String accessToken) {
|
||||
return this.tokenStore.readAccessToken(accessToken);
|
||||
}
|
||||
|
||||
public OAuth2Authentication loadAuthentication(String accessTokenValue) throws AuthenticationException, InvalidTokenException {
|
||||
OAuth2AccessToken accessToken = this.tokenStore.readAccessToken(accessTokenValue);
|
||||
if (accessToken == null) {
|
||||
throw new InvalidTokenException("Invalid access token: " + accessTokenValue);
|
||||
} else if (accessToken.isExpired()) {
|
||||
this.tokenStore.removeAccessToken(accessToken);
|
||||
throw new InvalidTokenException("Access token expired: " + accessTokenValue);
|
||||
} else {
|
||||
OAuth2Authentication result = this.tokenStore.readAuthentication(accessToken);
|
||||
if (result == null) {
|
||||
throw new InvalidTokenException("Invalid access token: " + accessTokenValue);
|
||||
} else {
|
||||
if (this.clientDetailsService != null) {
|
||||
String clientId = result.getOAuth2Request().getClientId();
|
||||
|
||||
try {
|
||||
this.clientDetailsService.loadClientByClientId(clientId);
|
||||
} catch (ClientRegistrationException var6) {
|
||||
throw new InvalidTokenException("Client not valid: " + clientId, var6);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getClientId(String tokenValue) {
|
||||
OAuth2Authentication authentication = this.tokenStore.readAuthentication(tokenValue);
|
||||
if (authentication == null) {
|
||||
throw new InvalidTokenException("Invalid access token: " + tokenValue);
|
||||
} else {
|
||||
OAuth2Request clientAuth = authentication.getOAuth2Request();
|
||||
if (clientAuth == null) {
|
||||
throw new InvalidTokenException("Invalid access token (no client id): " + tokenValue);
|
||||
} else {
|
||||
return clientAuth.getClientId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean revokeToken(String tokenValue) {
|
||||
OAuth2AccessToken accessToken = this.tokenStore.readAccessToken(tokenValue);
|
||||
if (accessToken == null) {
|
||||
return false;
|
||||
} else {
|
||||
if (accessToken.getRefreshToken() != null) {
|
||||
this.tokenStore.removeRefreshToken(accessToken.getRefreshToken());
|
||||
}
|
||||
|
||||
this.tokenStore.removeAccessToken(accessToken);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private OAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) {
|
||||
if (!this.isSupportRefreshToken(authentication.getOAuth2Request())) {
|
||||
return null;
|
||||
} else {
|
||||
int validitySeconds = this.getRefreshTokenValiditySeconds(authentication.getOAuth2Request());
|
||||
String value = UUID.randomUUID().toString();
|
||||
return (OAuth2RefreshToken) (validitySeconds > 0 ? new DefaultExpiringOAuth2RefreshToken(value, new Date(System.currentTimeMillis() + (long) validitySeconds * 1000L)) : new DefaultOAuth2RefreshToken(value));
|
||||
}
|
||||
}
|
||||
|
||||
private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) {
|
||||
DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString());
|
||||
int validitySeconds = this.getAccessTokenValiditySeconds(authentication.getOAuth2Request());
|
||||
if (validitySeconds > 0) {
|
||||
token.setExpiration(new Date(System.currentTimeMillis() + (long) validitySeconds * 1000L));
|
||||
}
|
||||
|
||||
token.setRefreshToken(refreshToken);
|
||||
token.setScope(authentication.getOAuth2Request().getScope());
|
||||
return (OAuth2AccessToken) (this.accessTokenEnhancer != null ? this.accessTokenEnhancer.enhance(token, authentication) : token);
|
||||
}
|
||||
|
||||
protected int getAccessTokenValiditySeconds(OAuth2Request clientAuth) {
|
||||
if (this.clientDetailsService != null) {
|
||||
ClientDetails client = this.clientDetailsService.loadClientByClientId(clientAuth.getClientId());
|
||||
Integer validity = client.getAccessTokenValiditySeconds();
|
||||
if (validity != null) {
|
||||
return validity;
|
||||
}
|
||||
}
|
||||
|
||||
return this.accessTokenValiditySeconds;
|
||||
}
|
||||
|
||||
protected int getRefreshTokenValiditySeconds(OAuth2Request clientAuth) {
|
||||
if (this.clientDetailsService != null) {
|
||||
ClientDetails client = this.clientDetailsService.loadClientByClientId(clientAuth.getClientId());
|
||||
Integer validity = client.getRefreshTokenValiditySeconds();
|
||||
if (validity != null) {
|
||||
return validity;
|
||||
}
|
||||
}
|
||||
|
||||
return this.refreshTokenValiditySeconds;
|
||||
}
|
||||
|
||||
protected boolean isSupportRefreshToken(OAuth2Request clientAuth) {
|
||||
if (this.clientDetailsService != null) {
|
||||
ClientDetails client = this.clientDetailsService.loadClientByClientId(clientAuth.getClientId());
|
||||
return client.getAuthorizedGrantTypes().contains("refresh_token");
|
||||
} else {
|
||||
return this.supportRefreshToken;
|
||||
}
|
||||
}
|
||||
|
||||
public void setTokenEnhancer(TokenEnhancer accessTokenEnhancer) {
|
||||
this.accessTokenEnhancer = accessTokenEnhancer;
|
||||
}
|
||||
|
||||
public void setRefreshTokenValiditySeconds(int refreshTokenValiditySeconds) {
|
||||
this.refreshTokenValiditySeconds = refreshTokenValiditySeconds;
|
||||
}
|
||||
|
||||
public void setAccessTokenValiditySeconds(int accessTokenValiditySeconds) {
|
||||
this.accessTokenValiditySeconds = accessTokenValiditySeconds;
|
||||
}
|
||||
|
||||
public void setSupportRefreshToken(boolean supportRefreshToken) {
|
||||
this.supportRefreshToken = supportRefreshToken;
|
||||
}
|
||||
|
||||
public void setReuseRefreshToken(boolean reuseRefreshToken) {
|
||||
this.reuseRefreshToken = reuseRefreshToken;
|
||||
}
|
||||
|
||||
public void setTokenStore(TokenStore tokenStore) {
|
||||
this.tokenStore = tokenStore;
|
||||
}
|
||||
|
||||
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
|
||||
this.authenticationManager = authenticationManager;
|
||||
}
|
||||
|
||||
public void setClientDetailsService(ClientDetailsService clientDetailsService) {
|
||||
this.clientDetailsService = clientDetailsService;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
package cn.crtech.cloud.auth.config;
|
||||
|
||||
import cn.crtech.cloud.auth.service.system.AuthService;
|
||||
import cn.crtech.cloud.auth.wx.applet.WxAppletSecurityConfigurerConfig;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
/**
|
||||
* SpringSecurity配置
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
AuthService authService;
|
||||
|
||||
@Autowired
|
||||
private WxAppletSecurityConfigurerConfig wxAppletSecurityConfigurerConfig;
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests()
|
||||
.antMatchers("/oauth/token").permitAll()
|
||||
.antMatchers("/wx/**").permitAll()
|
||||
.antMatchers("/oauth/initRedis").permitAll()
|
||||
.requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
|
||||
.antMatchers("/rsa/publicKey").permitAll()
|
||||
.anyRequest().authenticated().and().httpBasic().and()
|
||||
.apply(wxAppletSecurityConfigurerConfig).and()
|
||||
.csrf().disable();// 关闭跨域
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public UserAuthenticationProvider userAuthenticationProvider() {
|
||||
UserAuthenticationProvider userAuthenticationProvider = new UserAuthenticationProvider();
|
||||
userAuthenticationProvider.setAuthUserService(authService);
|
||||
userAuthenticationProvider.setHideUserNotFoundExceptions(false);
|
||||
userAuthenticationProvider.setPasswordEncoder(passwordEncoder());
|
||||
return userAuthenticationProvider;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.authenticationProvider(userAuthenticationProvider());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
package cn.crtech.cloud.auth.config;
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
|
||||
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
|
||||
import cn.crtech.cloud.auth.mapper.WxMaAuthorizeMapper;
|
||||
import cn.crtech.cloud.auth.pojo.WxAppletConfig;
|
||||
import cn.crtech.cloud.auth.pojo.WxGzhConfig;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.common.error.WxRuntimeException;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
|
||||
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class WxMaConfiguration {
|
||||
|
||||
@Autowired
|
||||
WxMaAuthorizeMapper wxMaConfigMapper;
|
||||
|
||||
|
||||
@Bean
|
||||
public WxMaService wxMaService() {
|
||||
List<WxAppletConfig> configs = wxMaConfigMapper.getWxAppletConfigList();
|
||||
if (configs == null) {
|
||||
throw new WxRuntimeException("小程序配置出错,添加下相关配置,注意别配错了!");
|
||||
}
|
||||
WxMaService maService = new WxMaServiceImpl();
|
||||
maService.setMultiConfigs(
|
||||
configs.stream()
|
||||
.map(a -> {
|
||||
WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
|
||||
// WxMaDefaultConfigImpl config = new WxMaRedisConfigImpl(new JedisPool());
|
||||
// 使用上面的配置时,需要同时引入jedis-lock的依赖,否则会报类无法找到的异常
|
||||
config.setAppid(a.getAppId());
|
||||
config.setSecret(a.getAppSecret());
|
||||
config.setToken(a.getToken());
|
||||
config.setAesKey(a.getEncodingAesKey());
|
||||
config.setMsgDataFormat(a.getMsgDataFormat());
|
||||
return config;
|
||||
}).collect(Collectors.toMap(WxMaDefaultConfigImpl::getAppid, a -> a, (o, n) -> o)));
|
||||
return maService;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WxMpService wxMpService() {
|
||||
List<WxGzhConfig> configs = wxMaConfigMapper.getWxGzhConfigList();
|
||||
WxMpService wxMpService = new WxMpServiceImpl();
|
||||
wxMpService.setMultiConfigStorages(
|
||||
configs.stream()
|
||||
.map(a -> {
|
||||
WxMpDefaultConfigImpl wxMpConfigStorage = new WxMpDefaultConfigImpl();
|
||||
// 使用上面的配置时,需要同时引入jedis-lock的依赖,否则会报类无法找到的异常
|
||||
wxMpConfigStorage.setAppId(a.getAppId());
|
||||
wxMpConfigStorage.setSecret(a.getAppSecret());
|
||||
wxMpConfigStorage.setToken(a.getAppToken());
|
||||
wxMpConfigStorage.setAesKey(a.getAppAeskey());
|
||||
return wxMpConfigStorage;
|
||||
}).collect(Collectors.toMap(WxMpDefaultConfigImpl::getAppId, a -> a, (o, n) -> o)));
|
||||
return wxMpService;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package cn.crtech.cloud.auth.controller;
|
||||
|
||||
import cn.crtech.cloud.auth.pojo.Oauth2Token;
|
||||
import cn.crtech.cloud.auth.service.ResourceService;
|
||||
import cn.crtech.cloud.common.api.CommonResult;
|
||||
import cn.crtech.cloud.common.dto.Result;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 自定义Oauth2获取令牌接口
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/oauth")
|
||||
public class AuthController {
|
||||
private TokenEndpoint tokenEndpoint;
|
||||
private ResourceService resourceService;
|
||||
|
||||
@Autowired
|
||||
public AuthController(TokenEndpoint tokenEndpoint, ResourceService resourceService) {
|
||||
this.tokenEndpoint = tokenEndpoint;
|
||||
this.resourceService = resourceService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Oauth2登录认证
|
||||
*/
|
||||
@PostMapping("/token")
|
||||
public CommonResult<Oauth2Token> postAccessToken(Principal principal, @RequestParam Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
|
||||
OAuth2AccessToken oAuth2AccessToken = tokenEndpoint.postAccessToken(principal, parameters).getBody();
|
||||
Oauth2Token oauth2TokenDto = Oauth2Token.builder()
|
||||
.token(oAuth2AccessToken.getValue())
|
||||
.refreshToken(oAuth2AccessToken.getRefreshToken().getValue())
|
||||
.expiresIn(oAuth2AccessToken.getExpiresIn())
|
||||
.tokenHead("Bearer ").build();
|
||||
return CommonResult.success(oauth2TokenDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限缓存内容更新
|
||||
*
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/initRedis")
|
||||
public Result initRedis() {
|
||||
resourceService.initData();
|
||||
return Result.success(true);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package cn.crtech.cloud.auth.controller;
|
||||
|
||||
import com.nimbusds.jose.jwk.JWKSet;
|
||||
import com.nimbusds.jose.jwk.RSAKey;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.security.KeyPair;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 获取RSA公钥接口
|
||||
*/
|
||||
|
||||
@RestController
|
||||
public class KeyPairController {
|
||||
private KeyPair keyPair;
|
||||
|
||||
@Autowired
|
||||
private void setKeyPair(KeyPair keyPair) {
|
||||
this.keyPair = keyPair;
|
||||
}
|
||||
|
||||
@GetMapping("/rsa/publicKey")
|
||||
public Map<String, Object> getKey() {
|
||||
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
|
||||
RSAKey key = new RSAKey.Builder(publicKey).build();
|
||||
return new JWKSet(key).toJSONObject();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,116 @@
|
||||
package cn.crtech.cloud.auth.controller;
|
||||
|
||||
import cn.crtech.cloud.auth.pojo.RegisterUser;
|
||||
import cn.crtech.cloud.auth.pojo.WechatLoginRequest;
|
||||
import cn.crtech.cloud.auth.service.wx.applet.WxMaUserService;
|
||||
import cn.crtech.cloud.common.dto.Result;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 微信小程序用户接口
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/wx")
|
||||
public class WxMaUserController {
|
||||
private WxMaUserService wxMaUserService;
|
||||
|
||||
@Autowired
|
||||
public WxMaUserController(WxMaUserService wxMaUserService) {
|
||||
this.wxMaUserService = wxMaUserService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验是否关注、绑定
|
||||
*
|
||||
* @param wxAppletCode 微信小程序标识
|
||||
* @param code 参数标识
|
||||
* @param appId 公众号AppID
|
||||
* @return 返回校验结果
|
||||
*/
|
||||
@GetMapping("/checkUser")
|
||||
public Result checkUser(String wxAppletCode, String code, String appId) {
|
||||
return wxMaUserService.checkUser(wxAppletCode, code, appId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取微信用户对应绑定openID
|
||||
*
|
||||
* @param wxAppletCode 微信小程序标识
|
||||
* @param appId 公众号AppID
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@GetMapping("/getWxAppletOpenId")
|
||||
public Result getWxAppletOpenId(String wxAppletCode, String appId) {
|
||||
return wxMaUserService.getWxAppletOpenId(wxAppletCode, appId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 小程序绑定
|
||||
*
|
||||
* @param wechatLoginRequest 微信请求参数信息
|
||||
* @return 返回结果
|
||||
*/
|
||||
@PostMapping("/bindWxApplet")
|
||||
public Result bindWxApplet(@RequestBody WechatLoginRequest wechatLoginRequest) {
|
||||
return wxMaUserService.bindWxApplet(wechatLoginRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实名认证
|
||||
*
|
||||
* @param params 参数对象
|
||||
* <ul>
|
||||
* <li>userName: 用户名</li>
|
||||
* <li>mobile: 手机号码</li>
|
||||
* <li>idCard: 身份证号码</li>
|
||||
* </ul>
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/userMobileVerify")
|
||||
public Result userMobileVerify(@RequestBody Map<String, Object> params) {
|
||||
return wxMaUserService.userMobileVerify(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信用户登录
|
||||
*
|
||||
* @param code 登录参数
|
||||
* @return 返回登录结果
|
||||
*/
|
||||
@GetMapping("/login")
|
||||
public Result login(String code) {
|
||||
return wxMaUserService.login(code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过openId校验人员是否在该公司
|
||||
*
|
||||
* @param wxAppletCode 小程序标识
|
||||
* @param code 登录标识
|
||||
* @param appId 小程序APPId
|
||||
* @param companyCode 公司标识
|
||||
* @param companyName 公司名称
|
||||
* @return 返回校验结果
|
||||
*/
|
||||
@GetMapping("/checkWxRegisterUser")
|
||||
public Result checkWxRegisterUser(String wxAppletCode, String code, String appId, String companyCode, String companyName) {
|
||||
return wxMaUserService.checkWxRegisterUser(wxAppletCode, code, appId, companyCode, companyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 小程序 用户注册
|
||||
*
|
||||
* @param registerUser 参数对象
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/registerCompanyUser")
|
||||
public Result registerCompanyUser(@RequestBody RegisterUser registerUser) {
|
||||
return wxMaUserService.registerCompanyUser(registerUser);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package cn.crtech.cloud.auth.dto;
|
||||
|
||||
import cn.crtech.cloud.common.annotation.DataExportAnnotation;
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* desc
|
||||
*
|
||||
* @author TYP
|
||||
* @since 2023-08-08 10:20
|
||||
*/
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MisComRoleDto implements Serializable {
|
||||
@DataExportAnnotation("公司标识")
|
||||
private String companyCode;
|
||||
|
||||
@DataExportAnnotation("角色标识")
|
||||
private String roleCode;
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package cn.crtech.cloud.auth.dto;
|
||||
|
||||
import cn.crtech.cloud.common.annotation.DataExportAnnotation;
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 企业角色实体
|
||||
*
|
||||
* @author TYP
|
||||
* @since 2023-08-01 9:24
|
||||
*/
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MisComRoleUserDto implements Serializable {
|
||||
@DataExportAnnotation("所属公司标识")
|
||||
private String companyCode;
|
||||
|
||||
@DataExportAnnotation("角色ID")
|
||||
private Integer roleId;
|
||||
|
||||
@DataExportAnnotation("用户ID")
|
||||
private Integer userId;
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
package cn.crtech.cloud.auth.dto;
|
||||
|
||||
import cn.crtech.cloud.common.annotation.DataExportAnnotation;
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* desc
|
||||
*
|
||||
* @author TYP
|
||||
* @since 2023-08-08 10:20
|
||||
*/
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MisComUserDto implements Serializable {
|
||||
@DataExportAnnotation("公司标识")
|
||||
private String companyCode;
|
||||
|
||||
@DataExportAnnotation("公司名称")
|
||||
private String companyName;
|
||||
|
||||
@DataExportAnnotation("公司图标")
|
||||
private String logo;
|
||||
|
||||
@DataExportAnnotation("所在省地址")
|
||||
private String provinceName;
|
||||
|
||||
@DataExportAnnotation("所在市地址")
|
||||
private String cityName;
|
||||
|
||||
@DataExportAnnotation("所在区/县地址")
|
||||
private String countyName;
|
||||
|
||||
@DataExportAnnotation("详细地址")
|
||||
private String address;
|
||||
|
||||
@DataExportAnnotation("用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@DataExportAnnotation("是否公司所有人")
|
||||
private Boolean isOwner;
|
||||
|
||||
@DataExportAnnotation("职位")
|
||||
private String position;
|
||||
|
||||
@DataExportAnnotation("是否默认公司")
|
||||
private Integer isDefault;
|
||||
|
||||
@DataExportAnnotation("状态")
|
||||
private Integer state;
|
||||
|
||||
@DataExportAnnotation("职员编号")
|
||||
private String serialNo;
|
||||
|
||||
@DataExportAnnotation("用户别名")
|
||||
private String nickName;
|
||||
|
||||
@DataExportAnnotation("用户手机号码")
|
||||
private String mobile;
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package cn.crtech.cloud.auth.dto;
|
||||
|
||||
import cn.crtech.cloud.common.annotation.DataExportAnnotation;
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 授权角色API权限实体DTO
|
||||
*
|
||||
* @author TYP
|
||||
* @since 2023-08-09 11:15
|
||||
*/
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MisRoleApiDto implements Serializable {
|
||||
@DataExportAnnotation("对应产品系列ID")
|
||||
private Integer seriesId;
|
||||
|
||||
@DataExportAnnotation("对应产品系列标识")
|
||||
private String seriesCode;
|
||||
|
||||
@DataExportAnnotation("对应产品ID")
|
||||
private Integer appId;
|
||||
|
||||
@DataExportAnnotation("对应产品标识")
|
||||
private String appCode;
|
||||
|
||||
@DataExportAnnotation("对应产品版本ID")
|
||||
private Integer versionId;
|
||||
|
||||
@DataExportAnnotation("对应产品版本")
|
||||
private String version;
|
||||
|
||||
@DataExportAnnotation("对应产品菜单ID")
|
||||
private Integer popedomId;
|
||||
|
||||
@DataExportAnnotation("对应API路由")
|
||||
private String controller;
|
||||
|
||||
@DataExportAnnotation("对应角色名称")
|
||||
private String role;
|
||||
|
||||
@DataExportAnnotation("授权权限数据集合")
|
||||
private List<MisRoleApiDto> authorityList;
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package cn.crtech.cloud.auth.launcher;
|
||||
|
||||
import com.alibaba.cloud.nacos.registry.NacosAutoServiceRegistration;
|
||||
import com.alibaba.cloud.nacos.registry.NacosRegistration;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.Query;
|
||||
import javax.servlet.ServletContext;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.Set;
|
||||
|
||||
//使用launcher启动时使用 begin
|
||||
//@Component
|
||||
//使用launcher启动时使用 end
|
||||
public class NacosConfig implements ApplicationRunner {
|
||||
@Autowired
|
||||
private ServletContext servletContext;
|
||||
|
||||
@Autowired
|
||||
private NacosRegistration registration;
|
||||
|
||||
@Autowired(required = false)
|
||||
private NacosAutoServiceRegistration nacosAutoServiceRegistration;
|
||||
|
||||
public Integer getTomcatPort() throws MalformedObjectNameException {
|
||||
MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
|
||||
Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"), Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
|
||||
String port = objectNames.iterator().next().getKeyProperty("port");
|
||||
|
||||
return new Integer(port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
if (registration != null && servletContext != null) {
|
||||
try {
|
||||
Integer tomcatPort = getTomcatPort();
|
||||
registration.setPort(tomcatPort);
|
||||
registration.getMetadata().put("management.context-path", servletContext.getContextPath());
|
||||
nacosAutoServiceRegistration.start();
|
||||
} catch (MalformedObjectNameException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,275 @@
|
||||
package cn.crtech.cloud.auth.mapper;
|
||||
|
||||
import cn.crtech.cloud.auth.dto.MisComRoleUserDto;
|
||||
import cn.crtech.cloud.auth.dto.MisComUserDto;
|
||||
import cn.crtech.cloud.auth.dto.MisRoleApiDto;
|
||||
import cn.crtech.cloud.auth.pojo.MisApp;
|
||||
import cn.crtech.cloud.auth.pojo.MisUser;
|
||||
import org.apache.ibatis.annotations.*;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Repository
|
||||
public interface AuthorizeMapper {
|
||||
@Select("SELECT " +
|
||||
"a.id , a.nick_name as nickName , a.mobile , a.email , a.avatar , a.password , a.name , " +
|
||||
"a.id_card as idCard , a.id_card_prev as idCardPrev , a.id_card_next as idCardNext , " +
|
||||
"a.reg_time as regTime , a.state, a.lastModifier , a.lastModifyTime , a.real_name as realName , " +
|
||||
"a.is_system_admin as isSystemAdmin " +
|
||||
"FROM mis_user a " +
|
||||
"where a.mobile= #{mobile} and a.state = 1 ")
|
||||
@ResultType(MisUser.class)
|
||||
MisUser queryUserByMobile(@Param("mobile") String mobile);
|
||||
|
||||
@Select("<script> " +
|
||||
"select " +
|
||||
"a.code as companyCode , a.name as companyName , a.logo , " +
|
||||
"a.province_name as provinceName , a.city_name as cityName , a.county_name as countyName , " +
|
||||
"a.street as address, b.user_id AS userId, " +
|
||||
"CASE WHEN a.owner_id = #{userId} then 1 ELSE 0 end as isOwner, " +
|
||||
"IFNULL(b.position,'超级管理员') as position, " +
|
||||
"IFNULL(b.is_default,1) AS isDefault, " +
|
||||
"IFNULL(b.state,1) as state, " +
|
||||
"b.serial_no as serialNo " +
|
||||
"from mis_company a " +
|
||||
"inner join mis_company_user b on b.company_code = a.code " +
|
||||
"where b.user_id = #{userId} and b.state = 1 " +
|
||||
" <if test='companyCode != null'> and a.code = #{companyCode} </if> " +
|
||||
"order by b.is_default desc " +
|
||||
"</script>")
|
||||
@ResultType(MisComUserDto.class)
|
||||
List<MisComUserDto> queryCompanyUserByUserId(Map<String, Object> params);
|
||||
|
||||
@Select("select " +
|
||||
"a.company_code as companyCode , a.role_id as roleId , a.user_id as userId " +
|
||||
"from mis_com_role_user a " +
|
||||
"where a.company_code = #{companyCode} and a.user_id = #{userId}")
|
||||
@ResultType(MisComRoleUserDto.class)
|
||||
List<MisComRoleUserDto> queryCompanyRoleUser(@Param("userId") int userId,
|
||||
@Param("companyCode") String companyCode);
|
||||
|
||||
@Select("select " +
|
||||
"GROUP_CONCAT(b.role_code) " +
|
||||
"from mis_com_role_user a " +
|
||||
"left join mis_com_role b on a.role_id = b.id " +
|
||||
"where a.company_code = #{companyCode} and a.user_id = #{userId} " +
|
||||
"and b.state = 1 " +
|
||||
"group by a.user_id ")
|
||||
@ResultType(String.class)
|
||||
String queryUserRole(@Param("userId") int userId, @Param("companyCode") String companyCode);
|
||||
|
||||
@Select("select " +
|
||||
"GROUP_CONCAT( DISTINCT CONCAT(d.code , '_' , c.code , '_' , b.code)) as roles " +
|
||||
"from mis_app_defaultrole_user a " +
|
||||
"inner join mis_app_defaultrole b on a.role_id = b.id " +
|
||||
"inner join mis_app c on c.id = b.app_id " +
|
||||
"inner join mis_app_series d on d.id = c.series_id " +
|
||||
"where a.company_code = #{companyCode} and a.user_id = #{userId} " +
|
||||
"and b.state = 1 and c.state = 1 and d.state = 1" +
|
||||
"group by a.user_id")
|
||||
@ResultType(String.class)
|
||||
String queryUserDefaultRole(@Param("userId") int userId, @Param("companyCode") String companyCode);
|
||||
|
||||
@Insert({"insert into mis_user " +
|
||||
"(nick_name, mobile, email, avatar, password, name, state, real_name, reg_time) " +
|
||||
"values " +
|
||||
"(#{nickName}, #{mobile}, #{email}, #{avatar}, #{password}, #{name}, " +
|
||||
" #{state}, #{realName}, #{regTime, jdbcType=TIMESTAMP})"})
|
||||
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
|
||||
int insertUser(MisUser user);
|
||||
|
||||
@Update("update mis_user " +
|
||||
"set " +
|
||||
"real_name = #{realName}, " +
|
||||
"name = #{name}, " +
|
||||
"nick_name = #{nickName}, " +
|
||||
"avatar = #{avatar}, " +
|
||||
"email = #{email} " +
|
||||
"where mobile = #{mobile}")
|
||||
int updateRegisterUser(MisUser user);
|
||||
|
||||
@Insert({"insert into mis_company_user " +
|
||||
"(company_code, user_id, serial_no, is_default, state,is_owner) " +
|
||||
"values " +
|
||||
"(#{companyCode}, #{userId}, #{serialNo}, #{isDefault}, #{state}, #{isOwner})"})
|
||||
int insertCompanyUser(MisComUserDto companyUser);
|
||||
|
||||
@Update("update mis_company_user " +
|
||||
"set " +
|
||||
"serial_no = #{serialNo}, " +
|
||||
"state = #{state} " +
|
||||
"where company_code = #{companyCode} and user_id=#{userId}")
|
||||
int updateCompanyUser(MisComUserDto companyUser);
|
||||
|
||||
@Update("update mis_user " +
|
||||
"set id_card =#{idCard}, " +
|
||||
"real_name = #{realName} " +
|
||||
"where mobile = #{mobile}")
|
||||
int updateUserIdCard(@Param("idCard") String idCard, @Param("realName") String realName, @Param("mobile") String mobile);
|
||||
|
||||
@Select("select " +
|
||||
"a.id , b.type , a.code , a.name , a.description , a.logo , a.state , a.sort , " +
|
||||
"a.resource_ids as resourceIds, a.client_secret as clientSecret , a.scope , " +
|
||||
"a.authorized_grant_types as authorizedGrantTypes , " +
|
||||
"a.access_token_validity as accessTokenValidity, " +
|
||||
"a.refresh_token_validity as refreshTokenValidity, " +
|
||||
"a.web_server_redirect_uri as webServerRedirectUri, " +
|
||||
"a.authorities , a.auto_approve as autoApprove " +
|
||||
"from mis_app a " +
|
||||
"inner join mis_app_series b on a.series_id = b.id " +
|
||||
"where b.type = 1 and a.state = 1 and b.state = 1")
|
||||
@ResultType(MisApp.class)
|
||||
List<MisApp> getAll();
|
||||
|
||||
@Select("select " +
|
||||
"CONCAT('/' ,b.code, a.authority_code) as controller , " +
|
||||
"CONCAT(c.code ,'_' , b.code) as role " +
|
||||
"from mis_app_popedom_authority a " +
|
||||
"inner join mis_app b on b.id = a.app_id " +
|
||||
"inner join mis_app_series c on c.id = b.series_id " +
|
||||
"where a.state = 1 and b.state = 1 and c.state = 1 ")
|
||||
@ResultType(MisRoleApiDto.class)
|
||||
List<MisRoleApiDto> listLimitApi();
|
||||
|
||||
@Select("select " +
|
||||
"c.id as seriesId , c.code as seriesCode , b.code as appCode , b.id as appId , " +
|
||||
"a.id as versionId , a.version " +
|
||||
"from mis_app_grade a " +
|
||||
"inner join mis_app b on b.id = a.app_id " +
|
||||
"inner join mis_app_series c on c.id = b.series_id " +
|
||||
"where a.need_price = 0 and a.state = 1 and b.state = 1 and c.state = 1 ")
|
||||
@ResultType(MisRoleApiDto.class)
|
||||
List<MisRoleApiDto> listFreeApp();
|
||||
|
||||
@Select("select " +
|
||||
"e.id as seriesId , e.code as seriesCode , c.code as appCode , c.id as appId , " +
|
||||
"b.id as versionId , b.version , d.id as popedomId , " +
|
||||
"case when d.route = '/' then '' else CONCAT('/' ,c.code, d.route,'/**') end as controller, " +
|
||||
"'ALL' as role " +
|
||||
"from mis_app_grade_popedom a " +
|
||||
"inner join mis_app_grade b on a.grade_id = b.id and b.need_price = 0 " +
|
||||
"inner join mis_app c on c.id = b.app_id " +
|
||||
"inner join mis_app_popedom d on d.id = a.popedom_id " +
|
||||
"inner join mis_app_series e on e.id = c.series_id " +
|
||||
"where d.route <> '/' and d.route <> '#' " +
|
||||
"and b.state = 1 and c.state = 1 and d.state = 1 and e.state = 1 ")
|
||||
@ResultType(MisRoleApiDto.class)
|
||||
List<MisRoleApiDto> listFreeController();
|
||||
|
||||
@Select("select " +
|
||||
"e.id as seriesId , e.code as seriesCode , c.code as appCode , c.id as appId , " +
|
||||
"b.id as versionId , b.version , d.popedom_id as popedomId, " +
|
||||
"CONCAT('/' ,c.code, d.authority_code) as controller , 'ALL' as role " +
|
||||
"from mis_app_grade_popedom_authority a " +
|
||||
"inner join mis_app_grade b on a.grade_id = b.id and b.need_price = 0 " +
|
||||
"inner join mis_app c on c.id = b.app_id " +
|
||||
"inner join mis_app_popedom_authority d on d.id = a.authority_id " +
|
||||
"inner join mis_app_series e on e.id = c.series_id " +
|
||||
"where b.state = 1 and c.state = 1 and d.state = 1 and e.state = 1 ")
|
||||
@ResultType(MisRoleApiDto.class)
|
||||
List<MisRoleApiDto> listFreeAuthority();
|
||||
|
||||
@Select("select " +
|
||||
"CONCAT('/',code , '/' , code ,'Feign/**') as controller , 'ALL' as role " +
|
||||
"from mis_app " +
|
||||
"where state = 1 ")
|
||||
@ResultType(MisRoleApiDto.class)
|
||||
List<MisRoleApiDto> listAppFeignController();
|
||||
|
||||
@Select("select " +
|
||||
"case when c.route = '/' then '' else CONCAT('/' ,d.code, c.route,'/**') end as controller, " +
|
||||
"GROUP_CONCAT(DISTINCT concat( b.company_code, '_', b.id )) as role, " +
|
||||
"e.id as seriesId , e.code as seriesCode , d.code as appCode , d.id as appId , " +
|
||||
"c.id as popedomId " +
|
||||
"from mis_com_role_popedom a " +
|
||||
"inner join mis_com_role b on b.id = a.role_id " +
|
||||
"inner join mis_app_popedom c on a.popedom_id = c.id " +
|
||||
"inner join mis_app d on d.id = c.app_id " +
|
||||
"inner join mis_app_series e on e.id = d.series_id " +
|
||||
"where c.route <> '/' and c.route <> '#' " +
|
||||
"and b.state = 1 and c.state = 1 and d.state = 1 and e.state = 1 " +
|
||||
"GROUP BY c.route")
|
||||
@ResultType(MisRoleApiDto.class)
|
||||
List<MisRoleApiDto> listRoleController();
|
||||
|
||||
@Select("select " +
|
||||
"CONCAT('/' ,d.code, c.authority_code) as controller, " +
|
||||
"GROUP_CONCAT(DISTINCT concat( b.company_code, '_', b.id )) as role, " +
|
||||
"e.id as seriesId , e.code as seriesCode , d.code as appCode , d.id as appId , " +
|
||||
"c.id as popedomId " +
|
||||
"from mis_com_role_popedom_authority a " +
|
||||
"inner join mis_com_role b on b.id = a.role_id " +
|
||||
"inner join mis_app_popedom_authority c on a.authority_id = c.id " +
|
||||
"inner join mis_app d on d.id = c.app_id " +
|
||||
"inner join mis_app_series e on e.id = d.series_id " +
|
||||
"where b.state = 1 and c.state = 1 and d.state = 1 and e.state = 1 " +
|
||||
"GROUP BY c.authority_code")
|
||||
@ResultType(MisRoleApiDto.class)
|
||||
List<MisRoleApiDto> listRoleAuthorityController();
|
||||
|
||||
@Select("select " +
|
||||
"case when d.route = '/' then '' else CONCAT('/' ,e.code, d.route , '/**') end as controller, " +
|
||||
"GROUP_CONCAT(DISTINCT concat( b.code, '_admin' )) as role, " +
|
||||
"f.id as seriesId , f.code as seriesCode , e.code as appCode , e.id as appId , " +
|
||||
"d.id as popedomId " +
|
||||
"from mis_com_app a " +
|
||||
"inner join mis_company b on a.company_id = b.id " +
|
||||
"left join mis_com_app_popedom c on c.company_id = b.id and c.app_id = a.app_id " +
|
||||
"inner join mis_app_popedom d on d.id = c.popedom_id " +
|
||||
"inner join mis_app e on e.id = a.app_id " +
|
||||
"inner join mis_app_series f on f.id = e.series_id " +
|
||||
"where d.route <> '/' and d.route <> '#' and a.state = 1 and a.expire_date >= now() " +
|
||||
"and d.state = 1 and e.state = 1 and f.state = 1 " +
|
||||
"group by d.route")
|
||||
@ResultType(MisRoleApiDto.class)
|
||||
List<MisRoleApiDto> getCompanyAdminController();
|
||||
|
||||
@Select("select " +
|
||||
"CONCAT('/' ,e.code, d.authority_code ) as controller, " +
|
||||
"GROUP_CONCAT(DISTINCT concat( b.code, '_admin' )) as role, " +
|
||||
"f.id as seriesId , f.code as seriesCode , e.code as appCode , e.id as appId ,d.id as popedomId " +
|
||||
"from mis_com_app a " +
|
||||
"inner join mis_company b on a.company_id = b.id " +
|
||||
"left join mis_com_app_popedom_authority c on c.company_id = b.id and c.app_id = a.app_id " +
|
||||
"inner join mis_app_popedom_authority d on d.id = c.authority_id " +
|
||||
"inner join mis_app e on e.id = a.app_id " +
|
||||
"inner join mis_app_series f on f.id = e.series_id " +
|
||||
"where a.state = 1 and a.expire_date >= now() and d.state = 1 and e.state = 1 and f.state = 1 " +
|
||||
"group by d.authority_code")
|
||||
@ResultType(MisRoleApiDto.class)
|
||||
List<MisRoleApiDto> getCompanyAdminAuthorityController();
|
||||
|
||||
@Select("select " +
|
||||
"case when e.route = '/' then '' else CONCAT('/' ,b.code, e.route , '/**') end as controller, " +
|
||||
"GROUP_CONCAT(DISTINCT concat(c.code , '_' , b.code , '_' , a.code)) as role, " +
|
||||
"c.id as seriesId , c.code as seriesCode , b.code as appCode , b.id as appId , " +
|
||||
"e.id as popedomId " +
|
||||
"from mis_app_defaultrole a " +
|
||||
"inner join mis_app b on a.app_id = b.id " +
|
||||
"inner join mis_app_series c on c.id = b.series_id " +
|
||||
"left join mis_app_defaultrole_popedom d on d.role_id = a.id " +
|
||||
"inner join mis_app_popedom e on e.id = d.popedom_id " +
|
||||
"where e.route <> '/' and e.route <> '#' and a.state = 1 and b.state = 1 " +
|
||||
"and c.state = 1 and e.state = 1 " +
|
||||
"group by e.route")
|
||||
@ResultType(MisRoleApiDto.class)
|
||||
List<MisRoleApiDto> listDefaultRoleController();
|
||||
|
||||
@Select("select " +
|
||||
"CONCAT('/' ,b.code, e.authority_code) as controller, " +
|
||||
"GROUP_CONCAT(DISTINCT concat( c.code , '_' , b.code , '_' , a.code)) as role, " +
|
||||
"c.id as seriesId , c.code as seriesCode , b.code as appCode , b.id as appId , " +
|
||||
"e.id as popedomId " +
|
||||
"from mis_app_defaultrole a " +
|
||||
"inner join mis_app b on a.app_id = b.id " +
|
||||
"inner join mis_app_series c on c.id = b.series_id " +
|
||||
"left join mis_app_defaultrole_popedom_authority d on d.role_id = a.id " +
|
||||
"inner join mis_app_popedom_authority e on e.id = d.authority_id " +
|
||||
"where a.state = 1 and b.state = 1 and c.state = 1 and e.state = 1 " +
|
||||
"group by e.authority_code")
|
||||
@ResultType(MisRoleApiDto.class)
|
||||
List<MisRoleApiDto> listDefaultRoleAuthorityController();
|
||||
|
||||
}
|
||||
@ -0,0 +1,105 @@
|
||||
package cn.crtech.cloud.auth.mapper;
|
||||
|
||||
import cn.crtech.cloud.auth.dto.MisComUserDto;
|
||||
import cn.crtech.cloud.auth.pojo.WxAppletConfig;
|
||||
import cn.crtech.cloud.auth.pojo.WxAppletUser;
|
||||
import cn.crtech.cloud.auth.pojo.WxGzhConfig;
|
||||
import org.apache.ibatis.annotations.*;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface WxMaAuthorizeMapper {
|
||||
@Select("SELECT " +
|
||||
"a.id, a.nick_name as nickName, a.mobile as mobile, " +
|
||||
"a.open_id as openId, a.wx_open_id as wxOpenId " +
|
||||
"FROM wx_user a " +
|
||||
"where open_id = #{openId}")
|
||||
@ResultType(WxAppletUser.class)
|
||||
List<WxAppletUser> getUserByWxAppletOpenId(@Param("openId") String openId);
|
||||
|
||||
@Select("SELECT " +
|
||||
"a.id , a.app_id as appId , a.app_name as appName , a.app_secret as appSecret, " +
|
||||
"a.encoding_aes_key as encodingAesKey , a.token , a.msg_data_format as msgDataFormat " +
|
||||
"FROM wx_applet_config a " +
|
||||
"where status = 1 ")
|
||||
@ResultType(WxAppletConfig.class)
|
||||
List<WxAppletConfig> getWxAppletConfigList();
|
||||
|
||||
@Select("SELECT " +
|
||||
"a.id, a.app_id as appId, a.name, a.app_secret as appSecret, a.app_aeskey as appAeskey," +
|
||||
"a.app_token as appToken " +
|
||||
"FROM wx_gzh_config as a " +
|
||||
"where status = 1 ")
|
||||
@ResultType(WxGzhConfig.class)
|
||||
List<WxGzhConfig> getWxGzhConfigList();
|
||||
|
||||
@Select("SELECT " +
|
||||
"a.id, a.nick_name as nickName, a.mobile as mobile, a.open_id as openId, " +
|
||||
"a.wx_open_id as wxOpenId " +
|
||||
"FROM wx_user a " +
|
||||
"where a.open_id = #{openId} " +
|
||||
"and a.company_code = #{companyCode}")
|
||||
@ResultType(WxAppletUser.class)
|
||||
WxAppletUser getWxAppletUser(@Param("openId") String openId, @Param("companyCode") String companyCode);
|
||||
|
||||
@Select("SELECT " +
|
||||
"a.id, a.nick_name as nickName, a.mobile as mobile, a.open_id as openId, " +
|
||||
"a.wx_open_id as wxOpenId " +
|
||||
"FROM wx_user a " +
|
||||
"where wx_open_id = #{wxOpenId}")
|
||||
@ResultType(WxAppletUser.class)
|
||||
WxAppletUser getUserByWxOpenId(@Param("wxOpenId") String wxOpenId);
|
||||
|
||||
@Insert({"insert into wx_user " +
|
||||
"(nick_name, avatar_url, gender, country,province, city, mobile,open_id, union_id, " +
|
||||
"created, app_id,wx_open_id, company_code, company_name) " +
|
||||
"values" +
|
||||
"(#{nickName}, #{avatarUrl}, #{gender}, #{country}, #{province}, #{city}, #{mobile}, " +
|
||||
"#{openId}, #{unionId}, #{created, jdbcType=TIMESTAMP}, #{appId}, #{wxOpenId}, " +
|
||||
"#{companyCode}, #{companyName})"})
|
||||
int insertWxAppletUser(WxAppletUser wxAppletUser);
|
||||
|
||||
@Update("update wx_user " +
|
||||
"set " +
|
||||
"nick_name = #{nickName}, " +
|
||||
"avatar_url = #{avatarUrl}, " +
|
||||
"gender = #{gender}, " +
|
||||
"country = #{country}, " +
|
||||
"province = #{province}, " +
|
||||
"city = #{city}, " +
|
||||
"mobile = #{mobile}, " +
|
||||
"union_id = #{unionId}, " +
|
||||
"updated = #{updated} " +
|
||||
"where open_id = #{openId}")
|
||||
int updateWxAppletUser(WxAppletUser wxAppletUser);
|
||||
|
||||
@Select("select " +
|
||||
"a.id as userId,a.nick_name as nickName, a.mobile as mobile, " +
|
||||
"b.company_code as companyCode, b.state " +
|
||||
"from mis_user a " +
|
||||
"inner join mis_company_user b on a.id = b.user_id " +
|
||||
"where a.mobile = #{mobile} and b.company_code=#{companyCode}")
|
||||
@ResultType(MisComUserDto.class)
|
||||
MisComUserDto queryCompanyUser(@Param("companyCode") String companyCode,
|
||||
@Param("mobile") String mobile);
|
||||
|
||||
@Select("SELECT " +
|
||||
"a.id as userId, a.nick_name as nickName, a.mobile as mobile, " +
|
||||
"b.company_code as companyCode, b.state " +
|
||||
"FROM mis_user a " +
|
||||
"inner join mis_company_user b on a.id = b.user_id " +
|
||||
"where a.mobile = #{mobile}")
|
||||
@ResultType(MisComUserDto.class)
|
||||
List<MisComUserDto> getUserCompanyList(@Param("mobile") String mobile);
|
||||
|
||||
@Update("update mis_company_user " +
|
||||
"set " +
|
||||
"is_default = #{isDefault} " +
|
||||
"where company_code = #{companyCode} " +
|
||||
"and user_id = #{userId}")
|
||||
int updateCompanyDefault(@Param("companyCode") String companyCode,
|
||||
@Param("userId") int userId,
|
||||
@Param("isDefault") int isDefault);
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
package cn.crtech.cloud.auth.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class AuthorizeUser {
|
||||
private Integer id;
|
||||
|
||||
private String userName;
|
||||
|
||||
private String passWord;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private List<String> roles;
|
||||
|
||||
private String companyCode;
|
||||
|
||||
private String companyName;
|
||||
|
||||
private String mobile;
|
||||
|
||||
private String nickName;
|
||||
|
||||
private String email;
|
||||
|
||||
private Boolean isCompanyAdmin;
|
||||
|
||||
private String dataSource;
|
||||
|
||||
private Integer dataSourceId;
|
||||
|
||||
|
||||
public AuthorizeUser(Integer userId, String passWord, Integer status, String mobile, String nickName, String email, String companyName, boolean isCompanyAdmin) {
|
||||
this.id = userId;
|
||||
this.userName = mobile;
|
||||
this.passWord = passWord;
|
||||
this.status = status;
|
||||
this.mobile = mobile;
|
||||
this.nickName = nickName;
|
||||
this.email = email;
|
||||
this.isCompanyAdmin = isCompanyAdmin;
|
||||
this.companyName = companyName;
|
||||
}
|
||||
|
||||
public AuthorizeUser() {
|
||||
}
|
||||
}
|
||||
118
Auth/src/main/java/cn/crtech/cloud/auth/pojo/MisApp.java
Normal file
118
Auth/src/main/java/cn/crtech/cloud/auth/pojo/MisApp.java
Normal file
@ -0,0 +1,118 @@
|
||||
package cn.crtech.cloud.auth.pojo;
|
||||
|
||||
import cn.crtech.cloud.common.annotation.DataExportAnnotation;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* MIS授权产品实体对象
|
||||
*
|
||||
* @author TYP
|
||||
* @since 2023-07-13 15:34
|
||||
*/
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "mis_app")
|
||||
public class MisApp implements Serializable {
|
||||
@Id
|
||||
@DataExportAnnotation("主键id")
|
||||
private Integer id;
|
||||
|
||||
@Column(name = "series_id")
|
||||
@DataExportAnnotation("产品所属系列ID")
|
||||
private Integer seriesId;
|
||||
|
||||
@Column(name = "name")
|
||||
@DataExportAnnotation("产品名称")
|
||||
private String name;
|
||||
|
||||
@Column(name = "code")
|
||||
@DataExportAnnotation("产品标识")
|
||||
private String code;
|
||||
|
||||
@Column(name = "description")
|
||||
@DataExportAnnotation("产品描述信息")
|
||||
private String description;
|
||||
|
||||
@Column(name = "logo")
|
||||
@DataExportAnnotation("产品图标超链接")
|
||||
private String logo;
|
||||
|
||||
@Column(name = "sort")
|
||||
@DataExportAnnotation("产品排序")
|
||||
private String sort;
|
||||
|
||||
@Column(name = "resource_ids")
|
||||
private String resourceIds;
|
||||
|
||||
@Column(name = "client_secret")
|
||||
@DataExportAnnotation("产品秘钥")
|
||||
private String clientSecret;
|
||||
|
||||
@Builder.Default
|
||||
@Column(name = "scope")
|
||||
@DataExportAnnotation("产品授权范围")
|
||||
private String scope = "all";
|
||||
|
||||
@Column(name = "web_server_redirect_uri")
|
||||
@DataExportAnnotation("")
|
||||
private String webServerRedirectUri;
|
||||
|
||||
@Column(name = "authorities")
|
||||
@DataExportAnnotation("")
|
||||
private String authorities;
|
||||
|
||||
@Column(name = "additional_information")
|
||||
@DataExportAnnotation("")
|
||||
private String additionalInformation;
|
||||
|
||||
@Builder.Default
|
||||
@Column(name = "authorized_grant_types")
|
||||
@DataExportAnnotation("产品授权加密类型")
|
||||
private String authorizedGrantTypes = "password,refresh_token";
|
||||
|
||||
@Builder.Default
|
||||
@Column(name = "access_token_validity")
|
||||
@DataExportAnnotation("访问授权TOKEN有效期")
|
||||
private Integer accessTokenValidity = 86400;
|
||||
|
||||
@Builder.Default
|
||||
@Column(name = "refresh_token_validity")
|
||||
@DataExportAnnotation("TOKEN刷新有效期")
|
||||
private Integer refreshTokenValidity = 86400;
|
||||
|
||||
@Column(name = "auto_approve")
|
||||
@DataExportAnnotation("")
|
||||
private String autoApprove;
|
||||
|
||||
@Column(name = "manager")
|
||||
@DataExportAnnotation("产品管理产品经理ID")
|
||||
private Integer manager;
|
||||
|
||||
@Column(name = "created")
|
||||
@DataExportAnnotation("创建时间")
|
||||
@JsonFormat(pattern = "YYYY-MM-dd HH:mm:ss", locale = "cn", timezone = "GMT+8")
|
||||
private Date created;
|
||||
|
||||
@Column(name = "is_default_role")
|
||||
@DataExportAnnotation("是否含有默认角色")
|
||||
private Boolean isDefaultRole;
|
||||
|
||||
@Column(name = "is_show")
|
||||
@DataExportAnnotation("是否默认展示在产品展示列表")
|
||||
private Boolean isShow;
|
||||
|
||||
@Column(name = "state")
|
||||
@DataExportAnnotation("状态 1正常 0停用 -1删除")
|
||||
private Integer state;
|
||||
}
|
||||
157
Auth/src/main/java/cn/crtech/cloud/auth/pojo/MisUser.java
Normal file
157
Auth/src/main/java/cn/crtech/cloud/auth/pojo/MisUser.java
Normal file
@ -0,0 +1,157 @@
|
||||
package cn.crtech.cloud.auth.pojo;
|
||||
|
||||
import cn.crtech.cloud.common.annotation.DataExportAnnotation;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 系统用户实体
|
||||
*
|
||||
* @author TYP
|
||||
* @since 2023-07-24 16:13
|
||||
*/
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "mis_user")
|
||||
public class MisUser implements Serializable {
|
||||
@Id
|
||||
@DataExportAnnotation("主键id")
|
||||
private Integer id;
|
||||
|
||||
@Column(name = "name")
|
||||
@DataExportAnnotation("用户名")
|
||||
private String name;
|
||||
|
||||
@Column(name = "mobile")
|
||||
@DataExportAnnotation("绑定手机号码")
|
||||
private String mobile;
|
||||
|
||||
@Column(name = "nick_name")
|
||||
@DataExportAnnotation("昵称")
|
||||
private String nickName;
|
||||
|
||||
@Column(name = "email")
|
||||
@DataExportAnnotation("绑定邮箱地址")
|
||||
private String email;
|
||||
|
||||
@Column(name = "avatar")
|
||||
@DataExportAnnotation("头像地址")
|
||||
private String avatar;
|
||||
|
||||
@Column(name = "password")
|
||||
@DataExportAnnotation("密码")
|
||||
private String password;
|
||||
|
||||
@Column(name = "id_card")
|
||||
@DataExportAnnotation("身份证号码")
|
||||
private String idCard;
|
||||
|
||||
@Column(name = "id_card_prev")
|
||||
@DataExportAnnotation("身份证正面图片地址")
|
||||
private String idCardPrev;
|
||||
|
||||
@Column(name = "id_card_next")
|
||||
@DataExportAnnotation("身份证反面图片地址")
|
||||
private String idCardNext;
|
||||
|
||||
@Column(name = "reg_time")
|
||||
@DataExportAnnotation("注册时间")
|
||||
@JsonFormat(pattern = "YYYY-MM-dd HH:mm:ss", locale = "cn", timezone = "GMT+8")
|
||||
private Date regTime;
|
||||
|
||||
@Column(name = "lastModifier")
|
||||
@DataExportAnnotation("最后一次修改人用户ID")
|
||||
private Integer lastModifier;
|
||||
|
||||
@Column(name = "lastModifyTime")
|
||||
@DataExportAnnotation("最后一次修改时间")
|
||||
@JsonFormat(pattern = "YYYY-MM-dd HH:mm:ss", locale = "cn", timezone = "GMT+8")
|
||||
private Date lastModifyTime;
|
||||
|
||||
@Column(name = "is_system_admin")
|
||||
@DataExportAnnotation("是否系统管理员")
|
||||
private Boolean isSystemAdmin;
|
||||
|
||||
@Column(name = "real_name")
|
||||
@DataExportAnnotation("用户真实姓名")
|
||||
private String realName;
|
||||
|
||||
@Column(name = "state")
|
||||
@DataExportAnnotation("状态 1正常 0停用 -1删除 ")
|
||||
private Integer state;
|
||||
|
||||
@Transient
|
||||
@DataExportAnnotation("查询条件 分页页码")
|
||||
private Integer pageNum;
|
||||
|
||||
@Transient
|
||||
@DataExportAnnotation("查询条件 分页个数")
|
||||
private Integer pageSize;
|
||||
|
||||
@Transient
|
||||
@DataExportAnnotation("修改内容 旧密码")
|
||||
private String oldPass;
|
||||
|
||||
@Transient
|
||||
@DataExportAnnotation("修改内容 新密码")
|
||||
private String newPass;
|
||||
|
||||
@Transient
|
||||
@DataExportAnnotation("修改内容 校验密码:二次输入新密码")
|
||||
private String checkPass;
|
||||
|
||||
@Transient
|
||||
@DataExportAnnotation("返回结果 所属企业名称")
|
||||
private String companyName;
|
||||
|
||||
@Transient
|
||||
@DataExportAnnotation("查询条件 产品标识")
|
||||
private String applicationCode;
|
||||
|
||||
@Transient
|
||||
@DataExportAnnotation("查询条件 角色标识")
|
||||
private String roleCode;
|
||||
|
||||
@Transient
|
||||
@DataExportAnnotation("修改内容 旧密码")
|
||||
private String oldPwd;
|
||||
|
||||
@Transient
|
||||
@DataExportAnnotation("修改内容 新密码")
|
||||
private String newPwd;
|
||||
|
||||
@Transient
|
||||
@DataExportAnnotation("修改内容 校验密码:二次输入新密码")
|
||||
private String checkNewPwd;
|
||||
|
||||
@Transient
|
||||
@DataExportAnnotation("参数内容 公司标识")
|
||||
private String companyCode;
|
||||
|
||||
@Transient
|
||||
@DataExportAnnotation("参数内容 用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Transient
|
||||
@DataExportAnnotation("参数内容 用户名称")
|
||||
private String userName;
|
||||
|
||||
@Transient
|
||||
@DataExportAnnotation("参数内容 员工编号")
|
||||
private String serialNo;
|
||||
|
||||
@Transient
|
||||
@DataExportAnnotation("返回结果 是否已经绑定角色")
|
||||
private Integer isBindRole;
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package cn.crtech.cloud.auth.pojo;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* Oauth2获取Token返回信息封装
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Builder
|
||||
public class Oauth2Token {
|
||||
/**
|
||||
* 访问令牌
|
||||
*/
|
||||
private String token;
|
||||
|
||||
/**
|
||||
* 刷新令牌
|
||||
*/
|
||||
private String refreshToken;
|
||||
|
||||
/**
|
||||
* 访问令牌头前缀
|
||||
*/
|
||||
private String tokenHead;
|
||||
|
||||
/**
|
||||
* 有效时间(秒)
|
||||
*/
|
||||
private int expiresIn;
|
||||
}
|
||||
20
Auth/src/main/java/cn/crtech/cloud/auth/pojo/RawDataDO.java
Normal file
20
Auth/src/main/java/cn/crtech/cloud/auth/pojo/RawDataDO.java
Normal file
@ -0,0 +1,20 @@
|
||||
package cn.crtech.cloud.auth.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RawDataDO {
|
||||
|
||||
private String nickName;
|
||||
|
||||
private String avatarUrl;
|
||||
|
||||
private Integer gender;
|
||||
|
||||
private String city;
|
||||
|
||||
private String country;
|
||||
|
||||
private String province;
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package cn.crtech.cloud.auth.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class RegisterUser implements Serializable {
|
||||
private Integer userId;
|
||||
private String nickName;
|
||||
private String email;
|
||||
private String serialNo;
|
||||
private String mobile;
|
||||
private String headImgUrl;
|
||||
private String companyCode;
|
||||
private String companyName;
|
||||
}
|
||||
115
Auth/src/main/java/cn/crtech/cloud/auth/pojo/SecurityUser.java
Normal file
115
Auth/src/main/java/cn/crtech/cloud/auth/pojo/SecurityUser.java
Normal file
@ -0,0 +1,115 @@
|
||||
package cn.crtech.cloud.auth.pojo;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 登录用户信息
|
||||
*/
|
||||
@Data
|
||||
public class SecurityUser implements UserDetails {
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
private String companyCode;
|
||||
|
||||
private String companyName;
|
||||
|
||||
/**
|
||||
* 用户密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 用户状态
|
||||
*/
|
||||
private Boolean enabled;
|
||||
|
||||
private String mobile;
|
||||
|
||||
private String nickName;
|
||||
|
||||
private String email;
|
||||
|
||||
private Boolean isCompanyAdmin;
|
||||
|
||||
private String dataSource;
|
||||
|
||||
private Integer dataSourceId;
|
||||
|
||||
/**
|
||||
* 权限数据
|
||||
*/
|
||||
private Collection<SimpleGrantedAuthority> authorities;
|
||||
|
||||
public SecurityUser() {
|
||||
|
||||
}
|
||||
|
||||
public SecurityUser(AuthorizeUser authorizeUser) {
|
||||
this.setId(authorizeUser.getId());
|
||||
this.setUserName(authorizeUser.getUserName());
|
||||
this.setCompanyCode(authorizeUser.getCompanyCode());
|
||||
this.setPassword(authorizeUser.getPassWord());
|
||||
this.setMobile(authorizeUser.getMobile());
|
||||
this.setNickName(authorizeUser.getNickName());
|
||||
this.setEnabled(authorizeUser.getStatus() == 1);
|
||||
this.setEmail(authorizeUser.getEmail());
|
||||
this.setIsCompanyAdmin(authorizeUser.getIsCompanyAdmin());
|
||||
this.setCompanyName(authorizeUser.getCompanyName());
|
||||
this.setDataSource(authorizeUser.getDataSource());
|
||||
this.setDataSourceId(authorizeUser.getDataSourceId());
|
||||
if (authorizeUser.getRoles() != null) {
|
||||
authorities = new ArrayList<>();
|
||||
authorizeUser.getRoles().forEach(item -> authorities.add(new SimpleGrantedAuthority(item)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return this.authorities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return this.password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return this.userName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
}
|
||||
92
Auth/src/main/java/cn/crtech/cloud/auth/pojo/User.java
Normal file
92
Auth/src/main/java/cn/crtech/cloud/auth/pojo/User.java
Normal file
@ -0,0 +1,92 @@
|
||||
package cn.crtech.cloud.auth.pojo;
|
||||
|
||||
|
||||
import cn.crtech.cloud.common.annotation.DataExportAnnotation;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Author : yj
|
||||
* Date : 2021-01-14
|
||||
* Description:
|
||||
*/
|
||||
@Data
|
||||
@Table(name = "user")
|
||||
@DataExportAnnotation("用户表")
|
||||
public class User implements Serializable {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@DataExportAnnotation("主键id")
|
||||
private Integer id;
|
||||
|
||||
@Column(name = "name")
|
||||
@DataExportAnnotation("姓名")
|
||||
private String name;
|
||||
|
||||
@Column(name = "id_card")
|
||||
@DataExportAnnotation("身份证")
|
||||
private String idCard;
|
||||
|
||||
@Column(name = "nick_name")
|
||||
@DataExportAnnotation("昵称")
|
||||
private String nickName;
|
||||
|
||||
@Column(name = "lastModifier")
|
||||
@DataExportAnnotation("最后修改人")
|
||||
private Long lastModifier;
|
||||
|
||||
@Column(name = "lastModifyTime")
|
||||
@DataExportAnnotation("最后修时间")
|
||||
private Date lastModifyTime;
|
||||
|
||||
@Column(name = "state")
|
||||
@DataExportAnnotation("状态")
|
||||
private Integer state;
|
||||
|
||||
@Column(name = "mobile")
|
||||
@DataExportAnnotation("手机号码")
|
||||
private String mobile;
|
||||
|
||||
@Column(name = "email")
|
||||
@DataExportAnnotation("邮箱")
|
||||
private String email;
|
||||
|
||||
@Column(name = "avatar")
|
||||
@DataExportAnnotation("头像")
|
||||
private String avatar;
|
||||
|
||||
@Column(name = "password")
|
||||
@DataExportAnnotation("密码")
|
||||
private String password;
|
||||
|
||||
@Column(name = "id_card_prev")
|
||||
@DataExportAnnotation("身份证正面")
|
||||
private String idCardPrev;
|
||||
|
||||
@Column(name = "id_card_next")
|
||||
@DataExportAnnotation("身份证反面")
|
||||
private String idCardNext;
|
||||
|
||||
@Column(name = "real_name")
|
||||
@DataExportAnnotation("真实姓名")
|
||||
private String realName;
|
||||
|
||||
@Column(name = "reg_time")
|
||||
@DataExportAnnotation("注册时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date regTime;
|
||||
|
||||
@Transient
|
||||
private String companyCode;
|
||||
|
||||
@Transient
|
||||
private String companyName;
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package cn.crtech.cloud.auth.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class WechatLoginRequest {
|
||||
private String rawData;
|
||||
private String signature;
|
||||
private String encryptedData;
|
||||
private String iv;
|
||||
private String username;
|
||||
private String password;
|
||||
private String accessToken;
|
||||
private String companyCode;
|
||||
private String companyName;
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package cn.crtech.cloud.auth.pojo;
|
||||
|
||||
|
||||
import cn.crtech.cloud.common.annotation.DataExportAnnotation;
|
||||
import cn.crtech.cloud.common.utils.IDGenerator;
|
||||
import lombok.Data;
|
||||
import tk.mybatis.mapper.annotation.KeySql;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
@Data
|
||||
@Table(name = "wx_applet_config")
|
||||
@DataExportAnnotation("小程序配置")
|
||||
public class WxAppletConfig implements Serializable {
|
||||
@Id
|
||||
@KeySql(genId = IDGenerator.class)
|
||||
@DataExportAnnotation("主键")
|
||||
private String id;
|
||||
|
||||
@Column(name = "app_id")
|
||||
@DataExportAnnotation("应用id")
|
||||
private String appId;
|
||||
|
||||
@Column(name = "app_name")
|
||||
@DataExportAnnotation("小程序名称")
|
||||
private String appName;
|
||||
|
||||
@Column(name = "app_secret")
|
||||
@DataExportAnnotation("秘钥")
|
||||
private String appSecret;
|
||||
|
||||
@Column(name = "encoding_aes_key")
|
||||
@DataExportAnnotation("消息加密key")
|
||||
private String encodingAesKey;
|
||||
|
||||
@Column(name = "token")
|
||||
@DataExportAnnotation("消息令牌")
|
||||
private String token;
|
||||
|
||||
@Column(name = "status")
|
||||
@DataExportAnnotation("状态")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 消息格式,XML或者JSON
|
||||
*/
|
||||
@Column(name = "msg_data_format")
|
||||
@DataExportAnnotation("消息格式")
|
||||
private String msgDataFormat;
|
||||
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
package cn.crtech.cloud.auth.pojo;
|
||||
|
||||
import cn.crtech.cloud.common.annotation.DataExportAnnotation;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@Table(name = "wx_user")
|
||||
@DataExportAnnotation("小程序用户")
|
||||
public class WxAppletUser {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@DataExportAnnotation("主键id")
|
||||
private Integer id;
|
||||
|
||||
@Column(name = "nick_name")
|
||||
@DataExportAnnotation("用户昵称")
|
||||
private String nickName;
|
||||
|
||||
@Column(name = "avatar_url")
|
||||
@DataExportAnnotation("用户头像")
|
||||
private String avatarUrl;
|
||||
|
||||
@Column(name = "gender")
|
||||
@DataExportAnnotation("性别")
|
||||
private int gender;
|
||||
|
||||
@Column(name = "country")
|
||||
@DataExportAnnotation("所在国家")
|
||||
private String country;
|
||||
|
||||
@Column(name = "province")
|
||||
@DataExportAnnotation("省份")
|
||||
private String province;
|
||||
|
||||
@Column(name = "city")
|
||||
@DataExportAnnotation("城市")
|
||||
private String city;
|
||||
|
||||
@Column(name = "mobile")
|
||||
@DataExportAnnotation("手机号码")
|
||||
private String mobile;
|
||||
|
||||
@Column(name = "open_id")
|
||||
@DataExportAnnotation("小程序openId")
|
||||
private String openId;
|
||||
|
||||
@Column(name = "union_id")
|
||||
@DataExportAnnotation("小程序unionId")
|
||||
private String unionId;
|
||||
|
||||
@Column(name = "app_id")
|
||||
@DataExportAnnotation("应用id")
|
||||
private String appId;
|
||||
|
||||
@Column(name = "wx_open_id")
|
||||
@DataExportAnnotation("微信openId")
|
||||
private String wxOpenId;
|
||||
|
||||
@Column(name = "created")
|
||||
@DataExportAnnotation("注册时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date created;
|
||||
|
||||
@Column(name = "updated")
|
||||
@DataExportAnnotation("更新时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date updated;
|
||||
|
||||
@Column(name = "qr_open_id")
|
||||
@DataExportAnnotation("扫二维码openId")
|
||||
private String qrOpenId;
|
||||
|
||||
@Column(name = "company_code")
|
||||
@DataExportAnnotation("企业标识")
|
||||
private String companyCode;
|
||||
|
||||
@Column(name = "company_name")
|
||||
@DataExportAnnotation("企业标识")
|
||||
private String companyName;
|
||||
|
||||
@Transient
|
||||
private String serialNo;
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package cn.crtech.cloud.auth.pojo;
|
||||
|
||||
|
||||
import cn.crtech.cloud.common.annotation.DataExportAnnotation;
|
||||
import cn.crtech.cloud.common.utils.IDGenerator;
|
||||
import lombok.Data;
|
||||
import tk.mybatis.mapper.annotation.KeySql;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
@Data
|
||||
@Table(name = "wx_gzh_config")
|
||||
@DataExportAnnotation("公众号号配置")
|
||||
public class WxGzhConfig implements Serializable {
|
||||
@Id
|
||||
@KeySql(genId = IDGenerator.class)
|
||||
@DataExportAnnotation("主键")
|
||||
private String id;
|
||||
|
||||
@Column(name = "name")
|
||||
@DataExportAnnotation("公众号名称")
|
||||
private String name;
|
||||
|
||||
@Column(name = "app_id")
|
||||
@DataExportAnnotation("应用id")
|
||||
private String appId;
|
||||
|
||||
@Column(name = "app_secret")
|
||||
@DataExportAnnotation("秘钥")
|
||||
private String appSecret;
|
||||
|
||||
@Column(name = "app_token")
|
||||
@DataExportAnnotation("消息令牌")
|
||||
private String appToken;
|
||||
|
||||
|
||||
@Column(name = "app_aeskey")
|
||||
@DataExportAnnotation("消息加密key")
|
||||
private String appAeskey;
|
||||
|
||||
@Column(name = "status")
|
||||
@DataExportAnnotation("状态")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
@ -0,0 +1,198 @@
|
||||
package cn.crtech.cloud.auth.service;
|
||||
|
||||
import cn.crtech.cloud.auth.dto.MisRoleApiDto;
|
||||
import cn.crtech.cloud.auth.mapper.AuthorizeMapper;
|
||||
import cn.crtech.cloud.common.constant.AuthConstant;
|
||||
import cn.crtech.cloud.common.constant.RedisConstant;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 资源与角色匹配关系管理业务类
|
||||
*/
|
||||
@Component
|
||||
public class ResourceService {
|
||||
private RedisTemplate redisTemplate;
|
||||
private AuthorizeMapper authorizeMapper;
|
||||
|
||||
@Autowired
|
||||
public ResourceService(RedisTemplate redisTemplate, AuthorizeMapper authorizeMapper) {
|
||||
this.redisTemplate = redisTemplate;
|
||||
this.authorizeMapper = authorizeMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化加载并将权限信息注入缓存
|
||||
*/
|
||||
@PostConstruct
|
||||
public void initData() {
|
||||
// 特殊权限授权内容加载处理
|
||||
initLimitAuthority();
|
||||
|
||||
// 免费角色权限数据内容加载处理
|
||||
initFreeController();
|
||||
|
||||
// 企业角色权限数据内容加载处理
|
||||
initComRoleController();
|
||||
|
||||
// 企业管理员权限数据内容加载处理
|
||||
initComAdminController();
|
||||
|
||||
// 产品默认角色权限数据内容加载处理
|
||||
initAppDefaultRoleController();
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存产品特殊权限内容
|
||||
*/
|
||||
private void initLimitAuthority() {
|
||||
redisTemplate.delete(RedisConstant.LIMIT_AUTHORITY_API_MAP);
|
||||
List<MisRoleApiDto> limitAuthority = authorizeMapper.listLimitApi();
|
||||
if (!CollectionUtils.isEmpty(limitAuthority)) {
|
||||
Map<String, String> limitAuthorityMap = new TreeMap<>();
|
||||
limitAuthority.forEach(item -> {
|
||||
limitAuthorityMap.put(item.getController(), item.getRole());
|
||||
});
|
||||
redisTemplate.opsForHash().putAll(RedisConstant.LIMIT_AUTHORITY_API_MAP, limitAuthorityMap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存免费产品及对应产品菜单权限功能
|
||||
*/
|
||||
private void initFreeController() {
|
||||
// 缓存免费产品及对应产品菜单权限功能
|
||||
List<MisRoleApiDto> freeAppList = authorizeMapper.listFreeApp();
|
||||
if (!CollectionUtils.isEmpty(freeAppList)) {
|
||||
// 相关菜单加载
|
||||
List<MisRoleApiDto> freeControllerList = authorizeMapper.listFreeController();
|
||||
// 相关菜单特殊权限加载
|
||||
List<MisRoleApiDto> freeAuthorityList = authorizeMapper.listFreeAuthority();
|
||||
|
||||
// 相关免费内容处理缓存 (根据产品分组ID、产品ID以及对应版本ID进行分组处理)
|
||||
freeAppList.forEach(item -> {
|
||||
String seriesAppVersion = RedisConstant.FREE_VERSION_API
|
||||
.replace("${SERIESCODE}", item.getSeriesCode())
|
||||
.replace("${APPCODE}", item.getAppCode())
|
||||
.replace("${VERSION}", item.getVersion());
|
||||
redisTemplate.delete(seriesAppVersion);
|
||||
|
||||
// 数据缓存处理
|
||||
Map<String, String> freeResourceMap = new TreeMap<>();
|
||||
List<MisRoleApiDto> tempList = freeControllerList.stream().filter(it -> it.getSeriesCode().equals(item.getSeriesCode())
|
||||
&& it.getAppCode().equals(item.getAppCode())
|
||||
&& it.getVersion().equals(item.getVersion()))
|
||||
.collect(Collectors.toList());
|
||||
tempList.forEach(temp -> {
|
||||
freeResourceMap.put(temp.getController(), temp.getRole());
|
||||
});
|
||||
|
||||
List<MisRoleApiDto> tempAuthorityList = freeAuthorityList.stream().filter(it -> it.getSeriesCode().equals(item.getSeriesCode())
|
||||
&& it.getAppCode().equals(item.getAppCode())
|
||||
&& it.getVersion().equals(item.getVersion()))
|
||||
.collect(Collectors.toList());
|
||||
tempAuthorityList.forEach(temp -> {
|
||||
freeResourceMap.put(temp.getController() + AuthConstant.APP_SPECIAL_AUTHORITY_SUFFIX, temp.getRole());
|
||||
});
|
||||
|
||||
freeResourceMap.put("/general/**", "ALL");
|
||||
freeResourceMap.put("/mns/**", "ALL");
|
||||
freeResourceMap.put("/rm/**", "ALL");
|
||||
freeResourceMap.put("/main/**", "ALL");
|
||||
redisTemplate.opsForHash().putAll(seriesAppVersion, freeResourceMap);
|
||||
});
|
||||
}
|
||||
|
||||
// 缓存产品内服务间调用内容
|
||||
redisTemplate.delete(RedisConstant.APP_FEIGN_API_MAP);
|
||||
List<MisRoleApiDto> appFeignList = authorizeMapper.listAppFeignController();
|
||||
if (!CollectionUtils.isEmpty(appFeignList)) {
|
||||
Map<String, String> appFeignMap = new TreeMap<>();
|
||||
appFeignList.forEach(item -> {
|
||||
appFeignMap.put(item.getController(), item.getRole());
|
||||
});
|
||||
redisTemplate.opsForHash().putAll(RedisConstant.APP_FEIGN_API_MAP, appFeignMap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存企业角色对应产品菜单权限功能
|
||||
*/
|
||||
private void initComRoleController() {
|
||||
redisTemplate.delete(RedisConstant.RESOURCE_ROLES_MAP);
|
||||
// 企业角色相关菜单加载
|
||||
List<MisRoleApiDto> comRoleApiList = authorizeMapper.listRoleController();
|
||||
// 企业角色相关菜单特殊权限加载
|
||||
List<MisRoleApiDto> comRoleAuthorityList = authorizeMapper.listRoleAuthorityController();
|
||||
// 企业角色相关内容处理缓存
|
||||
Map<String, String> comRoleMap = new TreeMap<>();
|
||||
comRoleApiList.forEach(item -> {
|
||||
comRoleMap.put(item.getController(), item.getRole());
|
||||
});
|
||||
comRoleAuthorityList.forEach(item -> {
|
||||
comRoleMap.put(item.getController() + AuthConstant.APP_SPECIAL_AUTHORITY_SUFFIX, item.getRole());
|
||||
});
|
||||
comRoleMap.put("/general/**", "ALL");
|
||||
comRoleMap.put("/mns/**", "ALL");
|
||||
comRoleMap.put("/rm/**", "ALL");
|
||||
comRoleMap.put("/main/**", "ALL");
|
||||
redisTemplate.opsForHash().putAll(RedisConstant.RESOURCE_ROLES_MAP, comRoleMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存企业管理员对应产品菜单权限功能
|
||||
*/
|
||||
private void initComAdminController() {
|
||||
redisTemplate.delete(RedisConstant.RESOURCE_ADMIN_MAP);
|
||||
// 企业管理员相关菜单加载
|
||||
List<MisRoleApiDto> comAdminController = authorizeMapper.getCompanyAdminController();
|
||||
// 企业管理员相关菜单特殊权限加载
|
||||
List<MisRoleApiDto> comAdminAuthorityController = authorizeMapper.getCompanyAdminAuthorityController();
|
||||
// 企业管理员相关内容处理缓存
|
||||
Map<String, String> comAdminMap = new TreeMap<>();
|
||||
comAdminController.forEach(item -> {
|
||||
comAdminMap.put(item.getController(), item.getRole());
|
||||
});
|
||||
comAdminAuthorityController.forEach(item -> {
|
||||
comAdminMap.put(item.getController() + AuthConstant.APP_SPECIAL_AUTHORITY_SUFFIX, item.getRole());
|
||||
});
|
||||
comAdminMap.put("/general/**", "ALL");
|
||||
comAdminMap.put("/mns/**", "ALL");
|
||||
comAdminMap.put("/rm/**", "ALL");
|
||||
comAdminMap.put("/main/**", "ALL");
|
||||
redisTemplate.opsForHash().putAll(RedisConstant.RESOURCE_ADMIN_MAP, comAdminMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存产品默认角色对应产品菜单权限功能
|
||||
*/
|
||||
private void initAppDefaultRoleController() {
|
||||
redisTemplate.delete(RedisConstant.DEFAULT_ROLES_MAP);
|
||||
|
||||
// 产品默认角色相关菜单加载
|
||||
List<MisRoleApiDto> appDefaultRoleApiList = authorizeMapper.listDefaultRoleController();
|
||||
// 产品默认角色相关菜单特殊权限加载
|
||||
List<MisRoleApiDto> appDefaultRoleAuthorityApiList = authorizeMapper.listDefaultRoleAuthorityController();
|
||||
// 产品默认角色关内容处理缓存
|
||||
Map<String, String> appDefaultRoleMap = new TreeMap<>();
|
||||
appDefaultRoleApiList.forEach(item -> {
|
||||
appDefaultRoleMap.put(item.getController(), item.getRole());
|
||||
});
|
||||
appDefaultRoleAuthorityApiList.forEach(item -> {
|
||||
appDefaultRoleMap.put(item.getController() + AuthConstant.APP_SPECIAL_AUTHORITY_SUFFIX, item.getRole());
|
||||
});
|
||||
appDefaultRoleMap.put("/general/**", "ALL");
|
||||
appDefaultRoleMap.put("/mns/**", "ALL");
|
||||
appDefaultRoleMap.put("/rm/**", "ALL");
|
||||
appDefaultRoleMap.put("/main/**", "ALL");
|
||||
redisTemplate.opsForHash().putAll(RedisConstant.DEFAULT_ROLES_MAP, appDefaultRoleMap);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,143 @@
|
||||
package cn.crtech.cloud.auth.service.system;
|
||||
|
||||
import cn.crtech.cloud.auth.dto.MisComRoleUserDto;
|
||||
import cn.crtech.cloud.auth.dto.MisComUserDto;
|
||||
import cn.crtech.cloud.auth.mapper.AuthorizeMapper;
|
||||
import cn.crtech.cloud.auth.pojo.AuthorizeUser;
|
||||
import cn.crtech.cloud.auth.pojo.MisUser;
|
||||
import cn.crtech.cloud.auth.pojo.SecurityUser;
|
||||
import cn.crtech.cloud.common.constant.MessageConstant;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AccountExpiredException;
|
||||
import org.springframework.security.authentication.CredentialsExpiredException;
|
||||
import org.springframework.security.authentication.DisabledException;
|
||||
import org.springframework.security.authentication.LockedException;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Author : yj
|
||||
* Date : 2021-01-14
|
||||
* Description:初始化登录用户信息,查询用户权限有哪些角色,以及登录接口loadUserByUsername
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@Slf4j
|
||||
public class AuthService implements AuthUserService {
|
||||
@Autowired
|
||||
AuthorizeMapper authorizeMapper;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写loadUserByUsername方法 后端登录token
|
||||
*
|
||||
* @param username 用户登录名称
|
||||
* @return 返回登录结果
|
||||
* @throws UsernameNotFoundException 用户登录名不存在异常
|
||||
*/
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username, String companyCode) throws UsernameNotFoundException {
|
||||
// 根据登录账号获取相关用户信息
|
||||
MisUser misUser = authorizeMapper.queryUserByMobile(username);
|
||||
if (ObjectUtils.isEmpty(misUser)) {
|
||||
throw new UsernameNotFoundException(MessageConstant.USERNAME_PASSWORD_ERROR);
|
||||
}
|
||||
|
||||
// 数据处理赋值
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("userId", misUser.getId());
|
||||
AuthorizeUser authorizeUser = new AuthorizeUser(misUser.getId(), misUser.getPassword(),
|
||||
misUser.getState(), username, misUser.getName(),
|
||||
misUser.getEmail(), "", false);
|
||||
if (StringUtils.isNotBlank(companyCode)) {
|
||||
params.put("companyCode", companyCode);
|
||||
}
|
||||
|
||||
// 其他授权信息获取处理
|
||||
getUserAuthorize(misUser, params, authorizeUser);
|
||||
|
||||
// 安全用户新增赋值
|
||||
SecurityUser securityUser = new SecurityUser(authorizeUser);
|
||||
|
||||
// 登录用户异常问题处理
|
||||
if (!securityUser.isEnabled()) {
|
||||
throw new DisabledException(MessageConstant.ACCOUNT_DISABLED);
|
||||
}
|
||||
if (!securityUser.isAccountNonLocked()) {
|
||||
throw new LockedException(MessageConstant.ACCOUNT_LOCKED);
|
||||
}
|
||||
if (!securityUser.isAccountNonExpired()) {
|
||||
throw new AccountExpiredException(MessageConstant.ACCOUNT_EXPIRED);
|
||||
}
|
||||
if (!securityUser.isCredentialsNonExpired()) {
|
||||
throw new CredentialsExpiredException(MessageConstant.CREDENTIALS_EXPIRED);
|
||||
}
|
||||
|
||||
return securityUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户登录授权信息补充处理
|
||||
*
|
||||
* @param user 用户信息对象
|
||||
* @param params 其他信息
|
||||
* @param authorizeUser 授权用户对象
|
||||
*/
|
||||
private void getUserAuthorize(MisUser user, Map<String, Object> params, AuthorizeUser authorizeUser) {
|
||||
List<MisComUserDto> companyList = authorizeMapper.queryCompanyUserByUserId(params);
|
||||
if (CollectionUtils.isEmpty(companyList)) {
|
||||
List<String> userRoleList = new ArrayList<>();
|
||||
userRoleList.add("ALL");
|
||||
authorizeUser.setRoles(userRoleList);
|
||||
authorizeUser.setDataSource("");
|
||||
} else {
|
||||
// 获取默认企业
|
||||
MisComUserDto defaultCompany = companyList.get(0);
|
||||
|
||||
authorizeUser.setCompanyCode(defaultCompany.getCompanyCode());
|
||||
authorizeUser.setCompanyName(defaultCompany.getCompanyName());
|
||||
|
||||
List<String> userRoleList = new ArrayList<>();
|
||||
userRoleList.add("ALL");
|
||||
|
||||
//设置企业管理员
|
||||
if (defaultCompany.getIsOwner()) {
|
||||
userRoleList.add(defaultCompany.getCompanyCode() + "_admin");
|
||||
authorizeUser.setIsCompanyAdmin(true);
|
||||
} else {
|
||||
// 查询获取授权角色数据集合
|
||||
List<MisComRoleUserDto> userRoles = authorizeMapper.queryCompanyRoleUser(user.getId(), defaultCompany.getCompanyCode());
|
||||
userRoles.forEach(role -> {
|
||||
userRoleList.add(role.getCompanyCode() + "_" + role.getRoleId());
|
||||
});
|
||||
|
||||
// 查询用户企业授权角色相关内容
|
||||
String comRoleCodes = authorizeMapper.queryUserRole(user.getId(), defaultCompany.getCompanyCode());
|
||||
if (!StringUtils.isBlank(comRoleCodes)) {
|
||||
String[] roleCodeArray = comRoleCodes.split(",");
|
||||
userRoleList.addAll(Arrays.asList(roleCodeArray));
|
||||
}
|
||||
|
||||
// 查询用户默认授权角色相关内容
|
||||
String defaultRoleCodes = authorizeMapper.queryUserDefaultRole(user.getId(), defaultCompany.getCompanyCode());
|
||||
if (!StringUtils.isBlank(defaultRoleCodes)) {
|
||||
String[] roleCodeArray = defaultRoleCodes.split(",");
|
||||
userRoleList.addAll(Arrays.asList(roleCodeArray));
|
||||
}
|
||||
}
|
||||
log.info("userRoleList ==> {}", userRoleList.toString());
|
||||
authorizeUser.setRoles(userRoleList);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package cn.crtech.cloud.auth.service.system;
|
||||
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
public interface AuthUserService extends UserDetailsService {
|
||||
UserDetails loadUserByUsername(String username, String companyCode) throws UsernameNotFoundException;
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package cn.crtech.cloud.auth.service.wx.applet;
|
||||
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
public interface WxAppletUserService extends UserDetailsService {
|
||||
UserDetails loadUserByUsername(String username, String companyCode) throws UsernameNotFoundException;
|
||||
}
|
||||
@ -0,0 +1,132 @@
|
||||
package cn.crtech.cloud.auth.service.wx.applet;
|
||||
|
||||
import cn.crtech.cloud.auth.dto.MisComRoleUserDto;
|
||||
import cn.crtech.cloud.auth.dto.MisComUserDto;
|
||||
import cn.crtech.cloud.auth.mapper.AuthorizeMapper;
|
||||
import cn.crtech.cloud.auth.mapper.WxMaAuthorizeMapper;
|
||||
import cn.crtech.cloud.auth.pojo.AuthorizeUser;
|
||||
import cn.crtech.cloud.auth.pojo.MisUser;
|
||||
import cn.crtech.cloud.auth.pojo.SecurityUser;
|
||||
import cn.crtech.cloud.auth.pojo.WxAppletUser;
|
||||
import cn.crtech.cloud.common.constant.MessageConstant;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AccountExpiredException;
|
||||
import org.springframework.security.authentication.CredentialsExpiredException;
|
||||
import org.springframework.security.authentication.DisabledException;
|
||||
import org.springframework.security.authentication.LockedException;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class WxAppletUserServiceImpl implements WxAppletUserService {
|
||||
private AuthorizeMapper authorizeMapper;
|
||||
private WxMaAuthorizeMapper wxMaAuthorizeMapper;
|
||||
|
||||
@Autowired
|
||||
public WxAppletUserServiceImpl(WxMaAuthorizeMapper wxMaAuthorizeMapper, AuthorizeMapper authorizeMapper) {
|
||||
this.wxMaAuthorizeMapper = wxMaAuthorizeMapper;
|
||||
this.authorizeMapper = authorizeMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重构微信用户登录内容
|
||||
*
|
||||
* @param username 登录账号
|
||||
* @param companyCode 公司标识
|
||||
* @return 返回登录处理结果
|
||||
* @throws UsernameNotFoundException 抛出异常
|
||||
*/
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username, String companyCode) throws UsernameNotFoundException {
|
||||
// 校验非空参数
|
||||
if (StringUtils.isBlank(username)) {
|
||||
throw new UsernameNotFoundException(MessageConstant.ACCOUNT_SIGNATURE_ERROR);
|
||||
}
|
||||
// 查询并校验对应微信用户是否存在
|
||||
WxAppletUser selectWxAppletUser = wxMaAuthorizeMapper.getUserByWxAppletOpenId(username).get(0);
|
||||
if (ObjectUtils.isEmpty(selectWxAppletUser)) {
|
||||
throw new UsernameNotFoundException(MessageConstant.ACCOUNT_ERROR);
|
||||
}
|
||||
// 查询并校验对应系统用户是否存在
|
||||
MisUser user = authorizeMapper.queryUserByMobile(selectWxAppletUser.getMobile());
|
||||
if (ObjectUtils.isEmpty(user)) {
|
||||
throw new UsernameNotFoundException(MessageConstant.ACCOUNT_ERROR);
|
||||
}
|
||||
|
||||
// 生成认证用户信息
|
||||
AuthorizeUser authorizeUser = new AuthorizeUser(user.getId(), user.getPassword(), user.getState(), user.getMobile(), user.getName(), user.getEmail(), "", false);
|
||||
|
||||
// 生成用户绑定企业信息相关查询参数
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("userId", user.getId());
|
||||
if (!StringUtils.isBlank(companyCode)) {
|
||||
params.put("companyCode", companyCode);
|
||||
}
|
||||
|
||||
// 查询用户关联企业信息内容
|
||||
List<MisComUserDto> comUserList = authorizeMapper.queryCompanyUserByUserId(params);
|
||||
if (CollectionUtils.isEmpty(comUserList)) {
|
||||
List<String> userRoleList = new ArrayList<>();
|
||||
userRoleList.add("ALL");
|
||||
authorizeUser.setRoles(userRoleList);
|
||||
} else {
|
||||
MisComUserDto defaultCompany = comUserList.get(0);
|
||||
List<String> userRoleList = new ArrayList<>();
|
||||
// 设置默认公司
|
||||
authorizeUser.setCompanyCode(defaultCompany.getCompanyCode());
|
||||
authorizeUser.setCompanyName(defaultCompany.getCompanyName());
|
||||
|
||||
// 判断是否企业管理员
|
||||
if (defaultCompany.getIsOwner()) {
|
||||
authorizeUser.setIsCompanyAdmin(true);
|
||||
userRoleList.add(defaultCompany.getCompanyCode() + "_admin");
|
||||
} else {
|
||||
List<MisComRoleUserDto> userRoles = authorizeMapper.queryCompanyRoleUser(user.getId(), defaultCompany.getCompanyCode());
|
||||
userRoles.forEach(role -> {
|
||||
userRoleList.add(role.getCompanyCode() + "_" + role.getRoleId());
|
||||
});
|
||||
|
||||
String roleCodes = authorizeMapper.queryUserRole(user.getId(), defaultCompany.getCompanyCode());
|
||||
if (!StringUtils.isBlank(roleCodes)) {
|
||||
String[] roleCodeArray = roleCodes.split(",");
|
||||
userRoleList.addAll(Arrays.asList(roleCodeArray));
|
||||
}
|
||||
String defaultRoleCodes = authorizeMapper.queryUserDefaultRole(user.getId(), defaultCompany.getCompanyCode());
|
||||
if (!StringUtils.isBlank(defaultRoleCodes)) {
|
||||
String[] roleCodeArray = defaultRoleCodes.split(",");
|
||||
userRoleList.addAll(Arrays.asList(roleCodeArray));
|
||||
}
|
||||
}
|
||||
userRoleList.add("ALL");
|
||||
authorizeUser.setRoles(userRoleList);
|
||||
}
|
||||
|
||||
SecurityUser securityUser = new SecurityUser(authorizeUser);
|
||||
if (!securityUser.isEnabled()) {
|
||||
throw new DisabledException(MessageConstant.ACCOUNT_DISABLED);
|
||||
}
|
||||
if (!securityUser.isAccountNonLocked()) {
|
||||
throw new LockedException(MessageConstant.ACCOUNT_LOCKED);
|
||||
}
|
||||
if (!securityUser.isAccountNonExpired()) {
|
||||
throw new AccountExpiredException(MessageConstant.ACCOUNT_EXPIRED);
|
||||
}
|
||||
if (!securityUser.isCredentialsNonExpired()) {
|
||||
throw new CredentialsExpiredException(MessageConstant.CREDENTIALS_EXPIRED);
|
||||
}
|
||||
return securityUser;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,574 @@
|
||||
package cn.crtech.cloud.auth.service.wx.applet;
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
||||
import cn.crtech.cloud.auth.dto.MisComUserDto;
|
||||
import cn.crtech.cloud.auth.mapper.AuthorizeMapper;
|
||||
import cn.crtech.cloud.auth.mapper.WxMaAuthorizeMapper;
|
||||
import cn.crtech.cloud.auth.pojo.*;
|
||||
import cn.crtech.cloud.auth.utils.TencentUtils;
|
||||
import cn.crtech.cloud.common.dto.Result;
|
||||
import cn.crtech.cloud.common.utils.EncryptUtil;
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
|
||||
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.result.WxMpUser;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.AlgorithmParameters;
|
||||
import java.security.Security;
|
||||
import java.util.*;
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class WxMaUserService {
|
||||
private static final String secretKey = "www.crtech.com";
|
||||
|
||||
private WxMpService wxMpService;
|
||||
private WxMaService wxMaService;
|
||||
private TencentUtils tencentUtils;
|
||||
private RedisTemplate redisTemplate;
|
||||
private PasswordEncoder passwordEncoder;
|
||||
private AuthorizeMapper authorizeMapper;
|
||||
private WxMaAuthorizeMapper wxMaConfigMapper;
|
||||
private WxMaAuthorizeMapper wxMaAuthorizeMapper;
|
||||
|
||||
@Autowired
|
||||
public WxMaUserService(WxMaService wxMaService, WxMaAuthorizeMapper wxMaConfigMapper,
|
||||
RedisTemplate redisTemplate, AuthorizeMapper authorizeMapper,
|
||||
WxMpService wxMpService, PasswordEncoder passwordEncoder,
|
||||
TencentUtils tencentUtils, WxMaAuthorizeMapper wxMaAuthorizeMapper) {
|
||||
this.wxMaService = wxMaService;
|
||||
this.wxMaConfigMapper = wxMaConfigMapper;
|
||||
this.redisTemplate = redisTemplate;
|
||||
this.authorizeMapper = authorizeMapper;
|
||||
this.wxMpService = wxMpService;
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
this.tencentUtils = tencentUtils;
|
||||
this.wxMaAuthorizeMapper = wxMaAuthorizeMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验是否关注、绑定
|
||||
*
|
||||
* @param wxAppletCode 微信小程序标识
|
||||
* @param code 参数标识
|
||||
* @param appId 公众号AppID
|
||||
* @return 返回校验结果
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public Result checkUser(String wxAppletCode, String code, String appId) {
|
||||
// 参数校验
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
if (!wxMaService.switchover(appId)) {
|
||||
throw new IllegalArgumentException(String.format("未找到对应 AppID=[%s] 的配置,请核实!", appId));
|
||||
}
|
||||
|
||||
try {
|
||||
WxOAuth2AccessToken accessToken = wxMpService.getOAuth2Service().getAccessToken(code);
|
||||
String wxOpenId = accessToken.getOpenId();
|
||||
WxMpUser wxMpUser = wxMpService.getUserService().userInfo(wxOpenId);
|
||||
boolean subscribe = wxMpUser.getSubscribe();
|
||||
WxOAuth2UserInfo wxOAuth2UserInfo = wxMpService.getOAuth2Service().getUserInfo(accessToken, wxOpenId);
|
||||
String headImgUrl = wxOAuth2UserInfo.getHeadImgUrl();
|
||||
log.info("wxOAuth2UserInfo ===> {}", wxOAuth2UserInfo.toString());
|
||||
|
||||
// 用户关注公众号校验
|
||||
if (!subscribe) {
|
||||
params.put("code", "unSubscribe");
|
||||
return Result.error(params, "未进行公众号绑定!");
|
||||
}
|
||||
|
||||
WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(wxAppletCode);
|
||||
String wxAppletOpenId = session.getOpenid();
|
||||
|
||||
//校验用户是否注册
|
||||
List<WxAppletUser> selectWxAppletUser = wxMaConfigMapper.getUserByWxAppletOpenId(wxAppletOpenId);
|
||||
if (selectWxAppletUser.isEmpty()) {
|
||||
//返回对应的token
|
||||
String sessionKey = session.getSessionKey();
|
||||
String systemAccessToken = createToken(wxAppletOpenId, sessionKey, appId, wxOpenId, headImgUrl, null, null);
|
||||
params.put("accessToken", systemAccessToken);
|
||||
params.put("code", "unBindApplet");
|
||||
return Result.error(params, "未进行系统绑定!");
|
||||
}
|
||||
|
||||
//校验通过 返回小程序openId
|
||||
params.put("openId", wxAppletOpenId);
|
||||
params.put("wxOpenId", wxOpenId);
|
||||
return Result.success(params);
|
||||
} catch (WxErrorException e) {
|
||||
params.put("code", "systemException");
|
||||
return Result.error(params, e.getError().getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取微信用户对应绑定openID
|
||||
*
|
||||
* @param wxAppletCode 微信小程序标识
|
||||
* @param appId 公众号AppID
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public Result getWxAppletOpenId(String wxAppletCode, String appId) {
|
||||
// 参数校验
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
if (!wxMaService.switchover(appId)) {
|
||||
throw new IllegalArgumentException(String.format("未找到对应 AppID=[%s] 的配置,请核实!", appId));
|
||||
}
|
||||
|
||||
try {
|
||||
WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(wxAppletCode);
|
||||
String wxAppletOpenId = session.getOpenid();
|
||||
//校验通过 返回小程序openId
|
||||
params.put("openId", wxAppletOpenId);
|
||||
return Result.success(params);
|
||||
} catch (WxErrorException e) {
|
||||
e.printStackTrace();
|
||||
params.put("code", "systemException");
|
||||
return Result.error(params, "非法code!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 小程序绑定
|
||||
*
|
||||
* @param request 微信请求参数信息
|
||||
* @return 返回结果
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Result bindWxApplet(WechatLoginRequest request) {
|
||||
// 参数非空校验
|
||||
if (StringUtils.isBlank(request.getUsername())) {
|
||||
return Result.error("", "参数异常: 用户名不能为空!");
|
||||
}
|
||||
if (StringUtils.isBlank(request.getPassword())) {
|
||||
return Result.error("", "参数异常: 用户密码不能为空!");
|
||||
}
|
||||
|
||||
// 其他公用对象内容生成
|
||||
String mobile = request.getUsername();
|
||||
String passWord = request.getPassword();
|
||||
|
||||
// 校验查询绑定用户
|
||||
MisUser misUser = authorizeMapper.queryUserByMobile(mobile);
|
||||
if (ObjectUtils.isEmpty(misUser)) {
|
||||
return Result.error("", "参数异常: 系统未查找到当前账号绑定用户!");
|
||||
}
|
||||
|
||||
// 登录密码校验
|
||||
if (!passwordEncoder.matches(passWord, misUser.getPassword())) {
|
||||
return Result.error("", "参数异常: 绑定密码与系统密码不符!");
|
||||
}
|
||||
|
||||
// 解析accessToken拆分对应授权信息
|
||||
String decryptAccessToken = new String(Objects.requireNonNull(
|
||||
EncryptUtil.decrypt(EncryptUtil.parseHexStr2Byte(request.getAccessToken()), secretKey)),
|
||||
StandardCharsets.UTF_8);
|
||||
Map accessTokenMap = JSONObject.parseObject(decryptAccessToken, Map.class);
|
||||
String openId = accessTokenMap.get("openId").toString();
|
||||
String sessionKey = accessTokenMap.get("sessionKey").toString();
|
||||
String appId = accessTokenMap.get("appId").toString();
|
||||
String wxOpenId = accessTokenMap.get("wxOpenId").toString();
|
||||
String headImgUrl = accessTokenMap.get("headImgUrl").toString();
|
||||
|
||||
// 创建生成 AppUser
|
||||
WxAppletUser insertOrUpdateDO = buildWechatUserAuthInfoDO(request.getRawData(),
|
||||
request.getEncryptedData(), request.getIv(), sessionKey, openId);
|
||||
insertOrUpdateDO.setMobile(mobile);
|
||||
|
||||
// 用户企业内容请求参数创建
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("userId", misUser.getId());
|
||||
if (!StringUtils.isBlank(request.getCompanyCode())) {
|
||||
params.put("companyCode", request.getCompanyCode());
|
||||
}
|
||||
|
||||
// 查询相关绑定企业内容并设置企业信息
|
||||
List<MisComUserDto> companyList = authorizeMapper.queryCompanyUserByUserId(params);
|
||||
if (CollectionUtils.isEmpty(companyList)) {
|
||||
if (StringUtils.isBlank(request.getCompanyCode()) && StringUtils.isBlank(request.getCompanyName())) {
|
||||
return Result.error(mobile, "绑定异常,请联系相关管理人员!");
|
||||
} else {
|
||||
insertOrUpdateDO.setCompanyCode(request.getCompanyCode());
|
||||
insertOrUpdateDO.setCompanyName(request.getCompanyName());
|
||||
insertOrUpdateDO.setSerialNo("No" + (int) ((Math.random() * 9 + 1)));
|
||||
}
|
||||
} else {
|
||||
MisComUserDto defaultCompany = companyList.get(0);
|
||||
if (!ObjectUtil.isEmpty(defaultCompany)) {
|
||||
insertOrUpdateDO.setCompanyCode(defaultCompany.getCompanyCode());
|
||||
insertOrUpdateDO.setCompanyName(defaultCompany.getCompanyName());
|
||||
insertOrUpdateDO.setSerialNo(defaultCompany.getSerialNo());
|
||||
}
|
||||
}
|
||||
|
||||
// 校验用户是否存在 不存在则插入 存在则进行更新
|
||||
int success = 0;
|
||||
WxAppletUser selectWxAppletUser = wxMaAuthorizeMapper.getWxAppletUser(openId, insertOrUpdateDO.getCompanyCode());
|
||||
if (ObjectUtils.isEmpty(selectWxAppletUser)) {
|
||||
insertOrUpdateDO.setWxOpenId(wxOpenId);
|
||||
insertOrUpdateDO.setAppId(appId);
|
||||
insertOrUpdateDO.setAvatarUrl(headImgUrl);
|
||||
success = wxMaAuthorizeMapper.insertWxAppletUser(insertOrUpdateDO);
|
||||
} else {
|
||||
selectWxAppletUser.setNickName(insertOrUpdateDO.getNickName());
|
||||
selectWxAppletUser.setAvatarUrl(headImgUrl);
|
||||
selectWxAppletUser.setGender(insertOrUpdateDO.getGender());
|
||||
selectWxAppletUser.setCountry(insertOrUpdateDO.getCountry());
|
||||
selectWxAppletUser.setProvince(insertOrUpdateDO.getProvince());
|
||||
selectWxAppletUser.setCity(insertOrUpdateDO.getCity());
|
||||
selectWxAppletUser.setMobile(insertOrUpdateDO.getMobile());
|
||||
selectWxAppletUser.setOpenId(insertOrUpdateDO.getOpenId());
|
||||
selectWxAppletUser.setUnionId(insertOrUpdateDO.getUnionId());
|
||||
success = wxMaAuthorizeMapper.updateWxAppletUser(selectWxAppletUser);
|
||||
}
|
||||
|
||||
if (success <= 0) {
|
||||
return Result.error(mobile, "绑定失败,请联系相关管理人员!");
|
||||
}
|
||||
|
||||
Map<String, Object> resultMap = new HashMap<>();
|
||||
resultMap.put("openId", openId);
|
||||
resultMap.put("wxOpenId", wxOpenId);
|
||||
resultMap.put("mobile", mobile);
|
||||
resultMap.put("headImgUrl", headImgUrl);
|
||||
resultMap.put("userId", misUser.getId());
|
||||
resultMap.put("nickName", misUser.getNickName());
|
||||
resultMap.put("serialNo", insertOrUpdateDO.getSerialNo());
|
||||
resultMap.put("companyCode", insertOrUpdateDO.getCompanyCode());
|
||||
resultMap.put("companyName", insertOrUpdateDO.getCompanyName());
|
||||
return Result.success(resultMap, "绑定成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 实名认证
|
||||
*
|
||||
* @param params 参数对象
|
||||
* <ul>
|
||||
* <li>userName: 用户名</li>
|
||||
* <li>mobile: 手机号码</li>
|
||||
* <li>idCard: 身份证号码</li>
|
||||
* </ul>
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Result userMobileVerify(Map<String, Object> params) {
|
||||
String userName = params.get("userName").toString();
|
||||
String mobile = params.get("mobile").toString();
|
||||
String idCard = params.get("idCard").toString();
|
||||
|
||||
MisUser misUser = authorizeMapper.queryUserByMobile(mobile);
|
||||
if (ObjectUtil.isEmpty(misUser)) {
|
||||
return Result.error(mobile, "未查找到当前用户");
|
||||
} else {
|
||||
if (!StringUtils.isBlank(misUser.getIdCard())) {
|
||||
return Result.error(mobile, "当前已实名过,请勿重复认证,如需修改,请联系客服!");
|
||||
} else {
|
||||
Result result = tencentUtils.releaseMobileVerify(userName, mobile, idCard);
|
||||
if (result.isSuccess()) {
|
||||
authorizeMapper.updateUserIdCard(idCard, userName, mobile);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信用户登录
|
||||
*
|
||||
* @param code 登录参数
|
||||
* @return 返回登录结果
|
||||
*/
|
||||
public Result login(String code) {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
try {
|
||||
WxOAuth2AccessToken accessToken = wxMpService.getOAuth2Service().getAccessToken("wx581b7b669d241777", "2d66509495044eea130e86e49d21be2d", code);
|
||||
//unionId 做为查询
|
||||
String unionId = accessToken.getUnionId();
|
||||
String wxOpenId = accessToken.getOpenId();
|
||||
WxOAuth2UserInfo wxOAuth2UserInfo = wxMpService.getOAuth2Service()
|
||||
.getUserInfo(accessToken, wxOpenId);
|
||||
System.out.println(wxOAuth2UserInfo.toString());
|
||||
} catch (WxErrorException e) {
|
||||
params.put("code", "systemException");
|
||||
return Result.error(params, e.getError().getErrorMsg());
|
||||
}
|
||||
return Result.success(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过openId校验人员是否在该公司
|
||||
*
|
||||
* @param wxAppletCode 小程序标识
|
||||
* @param code 登录标识
|
||||
* @param appId 小程序APPId
|
||||
* @param companyCode 公司标识
|
||||
* @param companyName 公司名称
|
||||
* @return 返回校验结果
|
||||
*/
|
||||
public Result checkWxRegisterUser(String wxAppletCode, String code, String appId, String companyCode, String companyName) {
|
||||
// 参数校验
|
||||
if (!wxMaService.switchover(appId)) {
|
||||
throw new IllegalArgumentException(String.format("未找到对应 AppID=[%s] 的配置,请核实!", appId));
|
||||
}
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
try {
|
||||
WxOAuth2AccessToken accessToken = wxMpService.getOAuth2Service().getAccessToken(code);
|
||||
String wxOpenId = accessToken.getOpenId();
|
||||
WxMpUser wxMpUser = wxMpService.getUserService().userInfo(wxOpenId);
|
||||
boolean subscribe = wxMpUser.getSubscribe();
|
||||
WxOAuth2UserInfo wxOAuth2UserInfo = wxMpService.getOAuth2Service().getUserInfo(accessToken, wxOpenId);
|
||||
String headImgUrl = wxOAuth2UserInfo.getHeadImgUrl();
|
||||
log.info("微信用户 ===> {}", wxOAuth2UserInfo.toString());
|
||||
|
||||
// 公众号校验
|
||||
if (!subscribe) {
|
||||
params.put("code", "unSubscribe");
|
||||
return Result.error(params, "未进行公众号绑定!");
|
||||
}
|
||||
|
||||
// 登录Session
|
||||
WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(wxAppletCode);
|
||||
String wxAppletOpenId = session.getOpenid();
|
||||
|
||||
// 校验用户是否绑定
|
||||
WxAppletUser selectWxAppletUser = wxMaConfigMapper.getWxAppletUser(wxAppletOpenId, companyCode);
|
||||
if (ObjectUtils.isEmpty(selectWxAppletUser)) {
|
||||
// 返回对应的token
|
||||
String sessionKey = session.getSessionKey();
|
||||
String loginAccessToken = createToken(wxAppletOpenId, sessionKey, appId, wxOpenId, headImgUrl,
|
||||
companyCode, companyName);
|
||||
params.put("accessToken", loginAccessToken);
|
||||
params.put("code", "unUserRegister");
|
||||
return Result.error(params, "未注册!");
|
||||
}
|
||||
|
||||
// 校验是否存在对应注册用户
|
||||
MisComUserDto misComUserDto = wxMaAuthorizeMapper.queryCompanyUser(companyCode, selectWxAppletUser.getMobile());
|
||||
if (ObjectUtils.isEmpty(misComUserDto)) {
|
||||
// 返回对应的token
|
||||
String sessionKey = session.getSessionKey();
|
||||
String loginAccessToken = createToken(wxAppletOpenId, sessionKey, appId, wxOpenId, headImgUrl,
|
||||
companyCode, companyName);
|
||||
params.put("accessToken", loginAccessToken);
|
||||
params.put("code", "unUserRegister");
|
||||
return Result.error(params, "未注册!");
|
||||
}
|
||||
|
||||
// 已注册 状态为禁用 需提示
|
||||
if (misComUserDto.getState() == 0) {
|
||||
params.put("code", "userException");
|
||||
return Result.error(null, "您已注册过,请勿重复注册,当前账号异常,请联系相关人员!");
|
||||
}
|
||||
|
||||
//校验通过 返回小程序openId
|
||||
params.put("openId", wxAppletOpenId);
|
||||
params.put("wxOpenId", wxOpenId);
|
||||
params.put("companyCode", companyCode);
|
||||
return Result.success(params);
|
||||
} catch (WxErrorException e) {
|
||||
params.put("code", "systemException");
|
||||
return Result.error(params, e.getError().getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 小程序 用户注册
|
||||
*
|
||||
* @param registerUser 参数对象
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
|
||||
public Result registerCompanyUser(RegisterUser registerUser) {
|
||||
// 校验对应手机号码是否存在绑定用户
|
||||
MisUser misUser = authorizeMapper.queryUserByMobile(registerUser.getMobile());
|
||||
Integer userId = null;
|
||||
if (ObjectUtils.isEmpty(misUser)) {
|
||||
MisUser user = new MisUser();
|
||||
user.setRealName(registerUser.getNickName());
|
||||
user.setNickName(registerUser.getNickName());
|
||||
user.setName(registerUser.getNickName());
|
||||
user.setEmail(StringUtils.isBlank(registerUser.getEmail()) ? "" : registerUser.getEmail());
|
||||
user.setMobile(registerUser.getMobile());
|
||||
PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
|
||||
String password = passwordEncoder.encode(registerUser.getMobile());
|
||||
user.setPassword(password.substring(8));
|
||||
user.setState(1);
|
||||
user.setRegTime(new Date());
|
||||
authorizeMapper.insertUser(user);
|
||||
userId = user.getId();
|
||||
} else {
|
||||
misUser.setRealName(registerUser.getNickName());
|
||||
misUser.setNickName(registerUser.getNickName());
|
||||
misUser.setName(registerUser.getNickName());
|
||||
if (!StringUtils.isBlank(registerUser.getEmail())) {
|
||||
misUser.setEmail(registerUser.getEmail());
|
||||
}
|
||||
//更新
|
||||
userId = misUser.getId();
|
||||
authorizeMapper.updateRegisterUser(misUser);
|
||||
}
|
||||
|
||||
// 查询相关公司用户数据并进行处理更新
|
||||
List<MisComUserDto> comUserList = wxMaAuthorizeMapper.getUserCompanyList(registerUser.getMobile());
|
||||
if (!CollectionUtils.isEmpty(comUserList)) {
|
||||
for (MisComUserDto companyUser : comUserList) {
|
||||
wxMaAuthorizeMapper.updateCompanyDefault(companyUser.getCompanyCode(), userId, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// 查询当前登录公司用户对象
|
||||
MisComUserDto selectCompanyUser = wxMaAuthorizeMapper.queryCompanyUser(registerUser.getCompanyCode(), registerUser.getMobile());
|
||||
String serialNo = StringUtils.isBlank(registerUser.getSerialNo()) ? ("No" + (int) ((Math.random() * 9 + 1) * 100000)) : registerUser.getSerialNo();
|
||||
if (ObjectUtils.isEmpty(selectCompanyUser)) {
|
||||
MisComUserDto companyUser = new MisComUserDto();
|
||||
companyUser.setUserId(userId);
|
||||
companyUser.setCompanyCode(registerUser.getCompanyCode());
|
||||
companyUser.setSerialNo(serialNo);
|
||||
companyUser.setState(1);
|
||||
companyUser.setIsDefault(1);
|
||||
companyUser.setIsOwner(false);
|
||||
authorizeMapper.insertCompanyUser(companyUser);
|
||||
} else {
|
||||
selectCompanyUser.setSerialNo(serialNo);
|
||||
selectCompanyUser.setState(1);
|
||||
selectCompanyUser.setIsDefault(1);
|
||||
authorizeMapper.updateCompanyUser(selectCompanyUser);
|
||||
}
|
||||
|
||||
//补足用户信息
|
||||
registerUser.setUserId(userId);
|
||||
registerUser.setSerialNo(serialNo);
|
||||
return Result.success(registerUser, "注册成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建访问Token
|
||||
*
|
||||
* @param openId 小程序用户openId
|
||||
* @param sessionKey session关键词
|
||||
* @param appId 小程序APPID
|
||||
* @param wxOpenId 微信用户OpenId
|
||||
* @param headImgUrl 头像地址
|
||||
* @param companyCode 公司标识
|
||||
* @param companyName 公司名称
|
||||
* @return 返回创建结果
|
||||
*/
|
||||
private static String createToken(String openId, String sessionKey, String appId, String wxOpenId,
|
||||
String headImgUrl, String companyCode, String companyName) {
|
||||
Map<String, Object> objectMap = new HashMap<>();
|
||||
objectMap.put("openId", openId);
|
||||
objectMap.put("sessionKey", sessionKey);
|
||||
objectMap.put("appId", appId);
|
||||
objectMap.put("wxOpenId", wxOpenId);
|
||||
objectMap.put("headImgUrl", headImgUrl);
|
||||
if (StringUtils.isNotEmpty(companyCode)) {
|
||||
objectMap.put("companyCode", companyCode);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(companyName)) {
|
||||
objectMap.put("companyName", companyName);
|
||||
}
|
||||
return EncryptUtil.parseByte2HexStr(Objects.requireNonNull(EncryptUtil.encrypt(JSON.toJSONString(objectMap), secretKey)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建AppUser
|
||||
*
|
||||
* @param rawData 行数据
|
||||
* @param encryptData 加密数据
|
||||
* @param iv 参数IV
|
||||
* @param sessionKey session关键词
|
||||
* @param openId 用户openId
|
||||
* @return 返回创建对象
|
||||
*/
|
||||
private WxAppletUser buildWechatUserAuthInfoDO(String rawData, String encryptData, String iv, String sessionKey, String openId) {
|
||||
WxAppletUser wxAppletUser = new WxAppletUser();
|
||||
wxAppletUser.setOpenId(openId);
|
||||
|
||||
if (!StringUtils.isBlank(rawData)) {
|
||||
RawDataDO rawDataDO = JSON.parseObject(rawData, RawDataDO.class);
|
||||
wxAppletUser.setNickName(rawDataDO.getNickName());
|
||||
wxAppletUser.setGender(rawDataDO.getGender());
|
||||
wxAppletUser.setCity(rawDataDO.getCity());
|
||||
wxAppletUser.setCountry(rawDataDO.getCountry());
|
||||
wxAppletUser.setProvince(rawDataDO.getProvince());
|
||||
}
|
||||
|
||||
// 解密加密信息,获取unionID
|
||||
if (!StringUtils.isBlank(encryptData)) {
|
||||
JSONObject encryptedData = getEncryptedData(encryptData, sessionKey, iv);
|
||||
if (encryptedData != null) {
|
||||
String unionId = encryptedData.getString("unionId");
|
||||
wxAppletUser.setUnionId(unionId);
|
||||
}
|
||||
}
|
||||
|
||||
return wxAppletUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密
|
||||
*
|
||||
* @param encryptedData 加密数据
|
||||
* @param sessionKey session关键词
|
||||
* @param iv 参数IV
|
||||
* @return 返回加密结果
|
||||
*/
|
||||
private JSONObject getEncryptedData(String encryptedData, String sessionKey, String iv) {
|
||||
// 被加密的数据
|
||||
byte[] dataByte = Base64.decode(encryptedData);
|
||||
// 加密秘钥
|
||||
byte[] keyByte = Base64.decode(sessionKey);
|
||||
// 偏移量
|
||||
byte[] ivByte = Base64.decode(iv);
|
||||
try {
|
||||
// 如果密钥不足16位,那么就补足.这个if中的内容很重要
|
||||
int base = 16;
|
||||
if (keyByte.length % base != 0) {
|
||||
int groups = keyByte.length / base + 1;
|
||||
byte[] temp = new byte[groups * base];
|
||||
Arrays.fill(temp, (byte) 0);
|
||||
System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
|
||||
keyByte = temp;
|
||||
}
|
||||
// 初始化
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
|
||||
SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
|
||||
AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
|
||||
parameters.init(new IvParameterSpec(ivByte));
|
||||
cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
|
||||
byte[] resultByte = cipher.doFinal(dataByte);
|
||||
if (null != resultByte && resultByte.length > 0) {
|
||||
String result = new String(resultByte, StandardCharsets.UTF_8);
|
||||
return JSONObject.parseObject(result);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("解密加密信息报错 ==> {}", e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
package cn.crtech.cloud.auth.service.wx.chat;
|
||||
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
|
||||
public interface WxChatUserService extends UserDetailsService {
|
||||
}
|
||||
@ -0,0 +1,131 @@
|
||||
package cn.crtech.cloud.auth.service.wx.chat;
|
||||
|
||||
import cn.crtech.cloud.auth.dto.MisComRoleUserDto;
|
||||
import cn.crtech.cloud.auth.dto.MisComUserDto;
|
||||
import cn.crtech.cloud.auth.mapper.AuthorizeMapper;
|
||||
import cn.crtech.cloud.auth.mapper.WxMaAuthorizeMapper;
|
||||
import cn.crtech.cloud.auth.pojo.*;
|
||||
import cn.crtech.cloud.common.constant.MessageConstant;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AccountExpiredException;
|
||||
import org.springframework.security.authentication.CredentialsExpiredException;
|
||||
import org.springframework.security.authentication.DisabledException;
|
||||
import org.springframework.security.authentication.LockedException;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class WxChatUserServiceImpl implements WxChatUserService {
|
||||
private AuthorizeMapper authorizeMapper;
|
||||
private WxMaAuthorizeMapper wxMaAuthorizeMapper;
|
||||
|
||||
@Autowired
|
||||
public WxChatUserServiceImpl(AuthorizeMapper authorizeMapper, WxMaAuthorizeMapper wxMaAuthorizeMapper) {
|
||||
this.authorizeMapper = authorizeMapper;
|
||||
this.wxMaAuthorizeMapper = wxMaAuthorizeMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重构微信用户登录内容
|
||||
*
|
||||
* @param username 登录账号
|
||||
* @return 返回登录处理结果
|
||||
* @throws UsernameNotFoundException 抛出异常
|
||||
*/
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
// 校验非空参数
|
||||
if (StringUtils.isBlank(username)) {
|
||||
throw new UsernameNotFoundException(MessageConstant.ACCOUNT_SIGNATURE_ERROR);
|
||||
}
|
||||
// 查询并校验对应微信用户是否存在
|
||||
WxAppletUser selectWxAppletUser = wxMaAuthorizeMapper.getUserByWxOpenId(username);
|
||||
if (ObjectUtils.isEmpty(selectWxAppletUser)) {
|
||||
throw new UsernameNotFoundException(MessageConstant.ACCOUNT_ERROR);
|
||||
}
|
||||
// 查询并校验对应系统用户是否存在
|
||||
MisUser user = authorizeMapper.queryUserByMobile(selectWxAppletUser.getMobile());
|
||||
if (ObjectUtils.isEmpty(user)) {
|
||||
throw new UsernameNotFoundException(MessageConstant.ACCOUNT_ERROR);
|
||||
}
|
||||
|
||||
// 生成用户绑定企业信息相关查询参数
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("userId", user.getId());
|
||||
|
||||
//生成认证用户信息
|
||||
AuthorizeUser authorizeUser = new AuthorizeUser(user.getId(), user.getPassword(), user.getState(), user.getMobile(), user.getName(), user.getEmail(), "", false);
|
||||
// getUserAuthorize(user, params, authorizeUser);
|
||||
|
||||
SecurityUser securityUser = new SecurityUser(authorizeUser);
|
||||
if (!securityUser.isEnabled()) {
|
||||
throw new DisabledException(MessageConstant.ACCOUNT_DISABLED);
|
||||
}
|
||||
if (!securityUser.isAccountNonLocked()) {
|
||||
throw new LockedException(MessageConstant.ACCOUNT_LOCKED);
|
||||
}
|
||||
if (!securityUser.isAccountNonExpired()) {
|
||||
throw new AccountExpiredException(MessageConstant.ACCOUNT_EXPIRED);
|
||||
}
|
||||
if (!securityUser.isCredentialsNonExpired()) {
|
||||
throw new CredentialsExpiredException(MessageConstant.CREDENTIALS_EXPIRED);
|
||||
}
|
||||
return securityUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户角色绑定信息补充
|
||||
*
|
||||
* @param user 用户对象
|
||||
* @param params 参数对象
|
||||
* @param authorizeUser 授权用户对象
|
||||
*/
|
||||
private void getUserAuthorize(User user, Map<String, Object> params, AuthorizeUser authorizeUser) {
|
||||
List<MisComUserDto> comUserList = authorizeMapper.queryCompanyUserByUserId(params);
|
||||
if (CollectionUtils.isEmpty(comUserList)) {
|
||||
List<String> userRoleList = new ArrayList<>();
|
||||
userRoleList.add("ALL");
|
||||
authorizeUser.setRoles(userRoleList);
|
||||
authorizeUser.setDataSource("");
|
||||
} else {
|
||||
// 获取当前企业
|
||||
MisComUserDto defaultCompany = comUserList.get(0);
|
||||
|
||||
authorizeUser.setCompanyCode(defaultCompany.getCompanyCode());
|
||||
authorizeUser.setCompanyName(defaultCompany.getCompanyName());
|
||||
List<String> userRoleList = new ArrayList<>();
|
||||
userRoleList.add("ALL");
|
||||
|
||||
// 设置企业管理员
|
||||
if (defaultCompany.getIsOwner()) {
|
||||
userRoleList.add(defaultCompany.getCompanyCode() + "_admin");
|
||||
authorizeUser.setIsCompanyAdmin(true);
|
||||
} else {
|
||||
List<MisComRoleUserDto> userRoles = authorizeMapper.queryCompanyRoleUser(user.getId(), defaultCompany.getCompanyCode());
|
||||
userRoles.forEach(role -> {
|
||||
userRoleList.add(role.getCompanyCode() + "_" + role.getRoleId());
|
||||
});
|
||||
|
||||
String roleCodes = authorizeMapper.queryUserRole(user.getId(), defaultCompany.getCompanyCode());
|
||||
if (!StringUtils.isBlank(roleCodes)) {
|
||||
String[] roleCodeArray = roleCodes.split(",");
|
||||
userRoleList.addAll(Arrays.asList(roleCodeArray));
|
||||
}
|
||||
String defaultRoleCodes = authorizeMapper.queryUserDefaultRole(user.getId(), defaultCompany.getCompanyCode());
|
||||
if (!StringUtils.isBlank(defaultRoleCodes)) {
|
||||
String[] roleCodeArray = defaultRoleCodes.split(",");
|
||||
userRoleList.addAll(Arrays.asList(roleCodeArray));
|
||||
}
|
||||
}
|
||||
authorizeUser.setRoles(userRoleList);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
package cn.crtech.cloud.auth.utils;
|
||||
|
||||
import cn.crtech.cloud.common.dto.Result;
|
||||
import com.tencentcloudapi.common.Credential;
|
||||
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
|
||||
import com.tencentcloudapi.common.profile.ClientProfile;
|
||||
import com.tencentcloudapi.common.profile.HttpProfile;
|
||||
import com.tencentcloudapi.faceid.v20180301.FaceidClient;
|
||||
import com.tencentcloudapi.faceid.v20180301.models.PhoneVerificationRequest;
|
||||
import com.tencentcloudapi.faceid.v20180301.models.PhoneVerificationResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TencentUtils {
|
||||
@Value("${tencent.release.mobile.secretId}")
|
||||
private String secretId;
|
||||
|
||||
@Value("${tencent.release.mobile.secretKey}")
|
||||
private String secretKey;
|
||||
|
||||
public Result releaseMobileVerify(String userName, String mobile, String idCard) {
|
||||
try {
|
||||
// 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKey,此处还需注意密钥对的保密
|
||||
Credential cred = new Credential(secretId, secretKey);
|
||||
|
||||
// 实例化一个http选项,可选的,没有特殊需求可以跳过
|
||||
HttpProfile httpProfile = new HttpProfile();
|
||||
httpProfile.setEndpoint("faceid.tencentcloudapi.com");
|
||||
|
||||
// 实例化一个client选项,可选的,没有特殊需求可以跳过
|
||||
ClientProfile clientProfile = new ClientProfile();
|
||||
clientProfile.setHttpProfile(httpProfile);
|
||||
|
||||
// 实例化要请求产品的client对象,clientProfile是可选的
|
||||
FaceidClient client = new FaceidClient(cred, "ap-guangzhou", clientProfile);
|
||||
|
||||
// 实例化一个请求对象,每个接口都会对应一个request对象
|
||||
PhoneVerificationRequest req = new PhoneVerificationRequest();
|
||||
req.setName(userName);
|
||||
req.setIdCard(idCard);
|
||||
req.setPhone(mobile);
|
||||
|
||||
// 返回的resp是一个PhoneVerificationResponse的实例,与请求对象对应
|
||||
PhoneVerificationResponse resp = client.PhoneVerification(req);
|
||||
|
||||
// 输出json格式的字符串回包
|
||||
log.info("三要素核验结果 ==> {} ", PhoneVerificationResponse.toJsonString(resp));
|
||||
int result = Integer.parseInt(resp.getResult());
|
||||
if (result == 0) {
|
||||
//认证通过
|
||||
return Result.success(null, resp.getDescription());
|
||||
} else if (result == -4) {
|
||||
return Result.error(null, "手机号码未匹配!");
|
||||
} else {
|
||||
return Result.error(null, resp.getDescription());
|
||||
}
|
||||
} catch (TencentCloudSDKException e) {
|
||||
log.info("手机三要素核验异常,错误代码 ==> {} , 错误内容 ==> {}", e.getErrorCode(), e.getMessage());
|
||||
return Result.error(null, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package cn.crtech.cloud.auth.wx.applet;
|
||||
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public class WxAppletAuthenticationFailureHandler implements AuthenticationFailureHandler {
|
||||
@Override
|
||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
|
||||
response.setContentType("text/plain;charset=UTF-8");
|
||||
response.getWriter().write("token失效!");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
package cn.crtech.cloud.auth.wx.applet;
|
||||
|
||||
import com.sun.istack.Nullable;
|
||||
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.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public class WxAppletAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
|
||||
// 设置拦截/sms/login短信登录接口
|
||||
private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER = new AntPathRequestMatcher("/wx/applet/oauth/token", "POST");
|
||||
|
||||
// 认证 请求参数
|
||||
private static final String accessTokenParam = "openId";
|
||||
private static final String companyCode = "companyCode";
|
||||
private boolean postOnly = true;
|
||||
|
||||
public WxAppletAuthenticationFilter() {
|
||||
super(DEFAULT_ANT_PATH_REQUEST_MATCHER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
|
||||
if (this.postOnly && !"POST".equals(request.getMethod())) {
|
||||
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
|
||||
} else {
|
||||
String accessToken = this.obtainAccessToken(request);
|
||||
accessToken = accessToken != null ? accessToken : "";
|
||||
accessToken = accessToken.trim();
|
||||
|
||||
String companyCode = this.obtainCompanyCode(request);
|
||||
companyCode = (companyCode != null) ? companyCode : "";
|
||||
|
||||
WxAppletAuthenticationToken authRequest = new WxAppletAuthenticationToken(accessToken, companyCode);
|
||||
this.setDetails(request, authRequest);
|
||||
// 认证信息
|
||||
return this.getAuthenticationManager().authenticate(authRequest);
|
||||
}
|
||||
}
|
||||
|
||||
protected String obtainCompanyCode(HttpServletRequest request) {
|
||||
return request.getParameter(this.companyCode);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected String obtainAccessToken(HttpServletRequest request) {
|
||||
return request.getParameter(this.accessTokenParam);
|
||||
}
|
||||
|
||||
protected void setDetails(HttpServletRequest request, WxAppletAuthenticationToken authRequest) {
|
||||
authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
|
||||
}
|
||||
|
||||
public void setPostOnly(boolean postOnly) {
|
||||
this.postOnly = postOnly;
|
||||
}
|
||||
|
||||
public final String getUsernameParameter() {
|
||||
return this.accessTokenParam;
|
||||
}
|
||||
|
||||
public final String getPasswordParameter() {
|
||||
return this.companyCode;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
package cn.crtech.cloud.auth.wx.applet;
|
||||
|
||||
import cn.crtech.cloud.auth.service.wx.applet.WxAppletUserServiceImpl;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.InternalAuthenticationServiceException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class WxAppletAuthenticationProvider implements AuthenticationProvider {
|
||||
private final WxAppletUserServiceImpl wxAppletUserService;
|
||||
|
||||
public WxAppletAuthenticationProvider(WxAppletUserServiceImpl wxAppletUserServiceImpl) {
|
||||
this.wxAppletUserService = wxAppletUserServiceImpl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
WxAppletAuthenticationToken wxAppletAuthenticationToken = (WxAppletAuthenticationToken) authentication;
|
||||
Object principal = authentication.getPrincipal();//token
|
||||
Object credentials = authentication.getCredentials();
|
||||
String accessToken = "";
|
||||
if (principal instanceof String) {
|
||||
accessToken = (String) principal;
|
||||
}
|
||||
String companyCode = "";
|
||||
if (credentials != null) {
|
||||
if (credentials instanceof String) {
|
||||
companyCode = (String) credentials;
|
||||
}
|
||||
}
|
||||
|
||||
UserDetails userDetails = wxAppletUserService.loadUserByUsername(accessToken, companyCode);
|
||||
if (userDetails == null) {
|
||||
throw new InternalAuthenticationServiceException("认证失败!");
|
||||
}
|
||||
|
||||
//重新创建已认证对象,
|
||||
WxAppletAuthenticationToken authenticationResult = new WxAppletAuthenticationToken(userDetails, companyCode, userDetails.getAuthorities());
|
||||
authenticationResult.setDetails(wxAppletAuthenticationToken.getDetails());
|
||||
return authenticationResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> authentication) {
|
||||
return WxAppletAuthenticationToken.class.isAssignableFrom(authentication);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
package cn.crtech.cloud.auth.wx.applet;
|
||||
|
||||
import cn.crtech.cloud.auth.component.JwtTokenEnhancer;
|
||||
import cn.crtech.cloud.auth.pojo.Oauth2Token;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
|
||||
import org.springframework.security.oauth2.provider.*;
|
||||
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
|
||||
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
@Component
|
||||
public class WxAppletAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
|
||||
@Override
|
||||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
|
||||
BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
|
||||
ClientDetailsService clientDetailsService = (ClientDetailsService) factory.getBean("clientDetailsService");
|
||||
AuthorizationServerTokenServices authorizationServerTokenServices = (AuthorizationServerTokenServices) factory.getBean("defaultAuthorizationServerTokenServices");
|
||||
JwtTokenEnhancer jwtTokenEnhancer = (JwtTokenEnhancer) factory.getBean("jwtTokenEnhancer");
|
||||
PasswordEncoder passwordEncoder = (PasswordEncoder) factory.getBean("passwordEncoder");
|
||||
|
||||
// 1. 从请求头中获取 ClientId
|
||||
String clientId = request.getParameter("client_id");
|
||||
String clientSecret = request.getParameter("client_secret");
|
||||
// 2. 通过 ClientDetailsService 获取 ClientDetails
|
||||
ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
|
||||
|
||||
TokenRequest tokenRequest = null;
|
||||
// 3. 校验 ClientId和 ClientSecret的正确性
|
||||
if (clientDetails == null) {
|
||||
throw new UnapprovedClientAuthenticationException("clientId:" + clientId + "对应的信息不存在");
|
||||
} else if (!passwordEncoder.matches(clientSecret, clientDetails.getClientSecret())) {
|
||||
throw new UnapprovedClientAuthenticationException("clientSecret不正确");
|
||||
} else {
|
||||
// 4. 通过 TokenRequest构造器生成 TokenRequest
|
||||
tokenRequest = new TokenRequest(new HashMap<>(), clientId, clientDetails.getScope(), "custom");
|
||||
}
|
||||
|
||||
// 5. 通过 TokenRequest的 createOAuth2Request方法获取 OAuth2Request
|
||||
OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
|
||||
// 6. 通过 Authentication和 OAuth2Request构造出 OAuth2Authentication
|
||||
OAuth2Authentication auth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
|
||||
// 7. 通过 AuthorizationServerTokenServices 生成 OAuth2AccessToken
|
||||
OAuth2AccessToken token = authorizationServerTokenServices.createAccessToken(auth2Authentication);
|
||||
OAuth2AccessToken resultToken = jwtTokenEnhancer.enhance(token, auth2Authentication);
|
||||
Oauth2Token oauth2TokenDto = Oauth2Token.builder()
|
||||
.token(resultToken.getValue())
|
||||
.refreshToken(resultToken.getRefreshToken().getValue())
|
||||
.expiresIn(resultToken.getExpiresIn())
|
||||
.tokenHead("Bearer ").build();
|
||||
// 8. 返回 Token
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
response.getWriter().write(JSON.toJSONString(oauth2TokenDto));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package cn.crtech.cloud.auth.wx.applet;
|
||||
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class WxAppletAuthenticationToken extends AbstractAuthenticationToken {
|
||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||
|
||||
//小程序openId
|
||||
private final Object principal;
|
||||
//企业code
|
||||
private Object credentials;
|
||||
|
||||
/**
|
||||
* Creates a token with the supplied array of authorities.
|
||||
*
|
||||
* @param principal
|
||||
*/
|
||||
public WxAppletAuthenticationToken(Object principal, Object credentials) {
|
||||
super(null);
|
||||
this.principal = principal;
|
||||
this.credentials = credentials;
|
||||
setAuthenticated(false);
|
||||
}
|
||||
|
||||
public WxAppletAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
|
||||
super(authorities);
|
||||
this.principal = principal;
|
||||
this.credentials = credentials;
|
||||
super.setAuthenticated(true); // must use super, as we override
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCredentials() {
|
||||
return this.credentials;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPrincipal() {
|
||||
return this.principal;
|
||||
}
|
||||
|
||||
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();
|
||||
this.credentials = null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package cn.crtech.cloud.auth.wx.applet;
|
||||
|
||||
import cn.crtech.cloud.auth.service.wx.applet.WxAppletUserServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class WxAppletSecurityConfigurerConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
|
||||
@Autowired
|
||||
private WxAppletUserServiceImpl wxAppletUserServiceImpl;
|
||||
|
||||
@Override
|
||||
public void configure(HttpSecurity http) throws Exception {
|
||||
//自定义SmsCodeAuthenticationFilter过滤器
|
||||
WxAppletAuthenticationFilter wxAppletAuthenticationFilter = new WxAppletAuthenticationFilter();
|
||||
wxAppletAuthenticationFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
|
||||
wxAppletAuthenticationFilter.setAuthenticationSuccessHandler(new WxAppletAuthenticationSuccessHandler());
|
||||
// 设置认证失败处理Handler
|
||||
wxAppletAuthenticationFilter.setAuthenticationFailureHandler(new WxAppletAuthenticationFailureHandler());
|
||||
WxAppletAuthenticationProvider wxAppletAuthenticationProvider = new WxAppletAuthenticationProvider(wxAppletUserServiceImpl);
|
||||
//在UsernamePasswordAuthenticationFilter过滤前执行
|
||||
http.authenticationProvider(wxAppletAuthenticationProvider)
|
||||
.addFilterAfter(wxAppletAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package cn.crtech.cloud.auth.wx.chat;
|
||||
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public class WxChatAuthenticationFailureHandler implements AuthenticationFailureHandler {
|
||||
@Override
|
||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
|
||||
response.setContentType("text/plain;charset=UTF-8");
|
||||
response.getWriter().write("token失效!");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package cn.crtech.cloud.auth.wx.chat;
|
||||
|
||||
import com.sun.istack.Nullable;
|
||||
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.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public class WxChatAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
|
||||
// 设置拦截/sms/login短信登录接口
|
||||
private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER = new AntPathRequestMatcher("/wx/chat/oauth/token", "POST");
|
||||
|
||||
// 认证 请求参数
|
||||
private static final String accessTokenParam = "openId";
|
||||
private boolean postOnly = true;
|
||||
|
||||
public WxChatAuthenticationFilter() {
|
||||
super(DEFAULT_ANT_PATH_REQUEST_MATCHER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
|
||||
if (this.postOnly && !"POST".equals(request.getMethod())) {
|
||||
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
|
||||
} else {
|
||||
String accessToken = this.obtainAccessToken(request);
|
||||
accessToken = accessToken != null ? accessToken : "";
|
||||
accessToken = accessToken.trim();
|
||||
|
||||
WxChatAuthenticationToken authRequest = new WxChatAuthenticationToken(accessToken);
|
||||
this.setDetails(request, authRequest);
|
||||
// 认证信息
|
||||
return this.getAuthenticationManager().authenticate(authRequest);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected String obtainAccessToken(HttpServletRequest request) {
|
||||
return request.getParameter(this.accessTokenParam);
|
||||
}
|
||||
|
||||
protected void setDetails(HttpServletRequest request, WxChatAuthenticationToken authRequest) {
|
||||
authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
|
||||
}
|
||||
|
||||
public void setPostOnly(boolean postOnly) {
|
||||
this.postOnly = postOnly;
|
||||
}
|
||||
|
||||
public final String getUsernameParameter() {
|
||||
return this.accessTokenParam;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package cn.crtech.cloud.auth.wx.chat;
|
||||
|
||||
import cn.crtech.cloud.auth.service.wx.chat.WxChatUserServiceImpl;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.InternalAuthenticationServiceException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class WxChatAuthenticationProvider implements AuthenticationProvider {
|
||||
private final WxChatUserServiceImpl wxChatUserService;
|
||||
|
||||
public WxChatAuthenticationProvider(WxChatUserServiceImpl wxChatUserService) {
|
||||
this.wxChatUserService = wxChatUserService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
WxChatAuthenticationToken wxAppletAuthenticationToken = (WxChatAuthenticationToken) authentication;
|
||||
Object principal = authentication.getPrincipal();//openId
|
||||
|
||||
String accessToken = "";
|
||||
if (principal instanceof String) {
|
||||
accessToken = (String) principal;
|
||||
}
|
||||
|
||||
UserDetails userDetails = wxChatUserService.loadUserByUsername(accessToken);
|
||||
if (userDetails == null) {
|
||||
throw new InternalAuthenticationServiceException("认证失败!");
|
||||
}
|
||||
|
||||
//重新创建已认证对象,
|
||||
WxChatAuthenticationToken authenticationResult = new WxChatAuthenticationToken(userDetails, userDetails.getAuthorities());
|
||||
authenticationResult.setDetails(wxAppletAuthenticationToken.getDetails());
|
||||
return authenticationResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> authentication) {
|
||||
return WxChatAuthenticationToken.class.isAssignableFrom(authentication);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
package cn.crtech.cloud.auth.wx.chat;
|
||||
|
||||
import cn.crtech.cloud.auth.component.JwtTokenEnhancer;
|
||||
import cn.crtech.cloud.auth.pojo.Oauth2Token;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
|
||||
import org.springframework.security.oauth2.provider.*;
|
||||
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
|
||||
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
@Component
|
||||
public class WxChatAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
|
||||
@Override
|
||||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
|
||||
BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
|
||||
ClientDetailsService clientDetailsService = (ClientDetailsService) factory.getBean("clientDetailsService");
|
||||
AuthorizationServerTokenServices authorizationServerTokenServices = (AuthorizationServerTokenServices) factory.getBean("defaultAuthorizationServerTokenServices");
|
||||
JwtTokenEnhancer jwtTokenEnhancer = (JwtTokenEnhancer) factory.getBean("jwtTokenEnhancer");
|
||||
PasswordEncoder passwordEncoder = (PasswordEncoder) factory.getBean("passwordEncoder");
|
||||
|
||||
// 1. 从请求头中获取 ClientId
|
||||
String clientId = request.getParameter("client_id");
|
||||
String clientSecret = request.getParameter("client_secret");
|
||||
// 2. 通过 ClientDetailsService 获取 ClientDetails
|
||||
ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
|
||||
|
||||
TokenRequest tokenRequest = null;
|
||||
// 3. 校验 ClientId和 ClientSecret的正确性
|
||||
if (clientDetails == null) {
|
||||
throw new UnapprovedClientAuthenticationException("clientId:" + clientId + "对应的信息不存在");
|
||||
} else if (!passwordEncoder.matches(clientSecret, clientDetails.getClientSecret())) {
|
||||
throw new UnapprovedClientAuthenticationException("clientSecret不正确");
|
||||
} else {
|
||||
// 4. 通过 TokenRequest构造器生成 TokenRequest
|
||||
tokenRequest = new TokenRequest(new HashMap<>(), clientId, clientDetails.getScope(), "custom");
|
||||
}
|
||||
|
||||
// 5. 通过 TokenRequest的 createOAuth2Request方法获取 OAuth2Request
|
||||
OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
|
||||
// 6. 通过 Authentication和 OAuth2Request构造出 OAuth2Authentication
|
||||
OAuth2Authentication auth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
|
||||
// 7. 通过 AuthorizationServerTokenServices 生成 OAuth2AccessToken
|
||||
OAuth2AccessToken token = authorizationServerTokenServices.createAccessToken(auth2Authentication);
|
||||
OAuth2AccessToken resultToken = jwtTokenEnhancer.enhance(token, auth2Authentication);
|
||||
Oauth2Token oauth2TokenDto = Oauth2Token.builder()
|
||||
.token(resultToken.getValue())
|
||||
.refreshToken(resultToken.getRefreshToken().getValue())
|
||||
.expiresIn(resultToken.getExpiresIn())
|
||||
.tokenHead("Bearer ").build();
|
||||
// 8. 返回 Token
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
response.getWriter().write(JSON.toJSONString(oauth2TokenDto));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package cn.crtech.cloud.auth.wx.chat;
|
||||
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class WxChatAuthenticationToken extends AbstractAuthenticationToken {
|
||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||
|
||||
//openId
|
||||
private final Object principal;
|
||||
|
||||
/**
|
||||
* Creates a token with the supplied array of authorities.
|
||||
*
|
||||
* @param principal
|
||||
*/
|
||||
public WxChatAuthenticationToken(Object principal) {
|
||||
super(null);
|
||||
this.principal = principal;
|
||||
setAuthenticated(false);
|
||||
}
|
||||
|
||||
public WxChatAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {
|
||||
super(authorities);
|
||||
this.principal = principal;
|
||||
super.setAuthenticated(true); // must use super, as we override
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCredentials() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPrincipal() {
|
||||
return this.principal;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package cn.crtech.cloud.auth.wx.chat;
|
||||
|
||||
import cn.crtech.cloud.auth.service.wx.chat.WxChatUserServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class WxChatSecurityConfigurerConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
|
||||
@Autowired
|
||||
private WxChatUserServiceImpl wxChatUserService;
|
||||
|
||||
@Override
|
||||
public void configure(HttpSecurity http) throws Exception {
|
||||
//自定义SmsCodeAuthenticationFilter过滤器
|
||||
WxChatAuthenticationFilter wxAppletAuthenticationFilter = new WxChatAuthenticationFilter();
|
||||
wxAppletAuthenticationFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
|
||||
wxAppletAuthenticationFilter.setAuthenticationSuccessHandler(new WxChatAuthenticationSuccessHandler());
|
||||
// 设置认证失败处理Handler
|
||||
wxAppletAuthenticationFilter.setAuthenticationFailureHandler(new WxChatAuthenticationFailureHandler());
|
||||
WxChatAuthenticationProvider wxAppletAuthenticationProvider = new WxChatAuthenticationProvider(wxChatUserService);
|
||||
//在UsernamePasswordAuthenticationFilter过滤前执行
|
||||
http.authenticationProvider(wxAppletAuthenticationProvider)
|
||||
.addFilterAfter(wxAppletAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
}
|
||||
}
|
||||
28
Auth/src/main/resources/application-dev.yml
Normal file
28
Auth/src/main/resources/application-dev.yml
Normal file
@ -0,0 +1,28 @@
|
||||
server:
|
||||
port: 9401
|
||||
servlet:
|
||||
encoding:
|
||||
charset: utf-8
|
||||
enabled: true
|
||||
force: true
|
||||
tomcat:
|
||||
uri-encoding: UTF-8
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: "*"
|
||||
mybatis:
|
||||
mapper-locations: classpath*:/mapping/*Mapper.xml
|
||||
type-aliases-package: cn.crtech.cloud.auth.pojo,cn.crtech.cloud.dto
|
||||
logging:
|
||||
config: classpath:logback.xml
|
||||
file:
|
||||
path: logs/crtech-cloud-auth.log
|
||||
level:
|
||||
cn.crtech.cloud.auth: debug
|
||||
tencent:
|
||||
release:
|
||||
mobile:
|
||||
secretId: AKIDZ5PL3jgQFnshIoD6wpPr32vaptkHDsmY
|
||||
secretKey: mQu42mHSP4hvsgXAVbYbIgnsC7l8NZLv
|
||||
17
Auth/src/main/resources/bootstrap-dev.yml
Normal file
17
Auth/src/main/resources/bootstrap-dev.yml
Normal file
@ -0,0 +1,17 @@
|
||||
spring:
|
||||
application:
|
||||
name: crtech-cloud-auth # 项目名称尽量用小写
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: localhost:8848
|
||||
redis:
|
||||
database: 4
|
||||
port: 6379
|
||||
host: localhost
|
||||
password:
|
||||
datasource:
|
||||
url: jdbc:mysql://chaoran.crtech.cn:9803/cr_cloud_auth_back?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
|
||||
username: crtech
|
||||
password: www.server41.com
|
||||
|
||||
6
Auth/src/main/resources/bootstrap.yml
Normal file
6
Auth/src/main/resources/bootstrap.yml
Normal file
@ -0,0 +1,6 @@
|
||||
spring:
|
||||
profiles:
|
||||
active: dev
|
||||
|
||||
|
||||
|
||||
BIN
Auth/src/main/resources/jwt.jks
Normal file
BIN
Auth/src/main/resources/jwt.jks
Normal file
Binary file not shown.
56
Auth/src/main/resources/logback.xml
Normal file
56
Auth/src/main/resources/logback.xml
Normal file
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="FILE"
|
||||
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>logs/crtech-cloud-auth.%d{yyyy-MM-dd}.log
|
||||
</fileNamePattern>
|
||||
</rollingPolicy>
|
||||
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd_HH:mm:ss} %logger{18} -%msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
|
||||
<discardingThreshold>0</discardingThreshold>
|
||||
<queueSize>1000</queueSize>
|
||||
<appender-ref ref="FILE" />
|
||||
</appender>
|
||||
|
||||
<logger name="org" level="info" additivity="false">
|
||||
<appender-ref ref="FILE"></appender-ref>
|
||||
<appender-ref ref="STDOUT"></appender-ref>
|
||||
</logger>
|
||||
<logger name="com" level="info" additivity="false">
|
||||
<appender-ref ref="FILE"></appender-ref>
|
||||
<appender-ref ref="STDOUT"></appender-ref>
|
||||
</logger>
|
||||
<logger name="net" level="info" additivity="false">
|
||||
<appender-ref ref="FILE"></appender-ref>
|
||||
<appender-ref ref="STDOUT"></appender-ref>
|
||||
</logger>
|
||||
|
||||
<logger name="com.netflix" level="debug" additivity="false">
|
||||
<appender-ref ref="STDOUT"></appender-ref>
|
||||
<appender-ref ref="FILE"></appender-ref>
|
||||
</logger>
|
||||
|
||||
<logger name="cn.crtech.cloud.auth" level="debug" additivity="false">
|
||||
<appender-ref ref="STDOUT"></appender-ref>
|
||||
<appender-ref ref="FILE"></appender-ref>
|
||||
</logger>
|
||||
<root level="INFO">
|
||||
<appender-ref ref="ASYNC" />
|
||||
</root>
|
||||
</configuration>
|
||||
170
Common/pom.xml
Normal file
170
Common/pom.xml
Normal file
@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
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>cn.crtech.cloud.common</groupId>
|
||||
<artifactId>Common</artifactId>
|
||||
<version>1.0.1</version>
|
||||
|
||||
<!-- 父工程 -->
|
||||
<parent>
|
||||
<groupId>cn.crtech.cloud.dependencies</groupId>
|
||||
<artifactId>Dependencies</artifactId>
|
||||
<version>1.0.1</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<!-- 依赖的版本锁定 -->
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<java.version>1.8</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
|
||||
<fastjson.version>1.2.83</fastjson.version>
|
||||
<thumbnailator.version>0.4.9</thumbnailator.version>
|
||||
<druid.version>1.2.8</druid.version>
|
||||
<mysql.version>8.0.27</mysql.version>
|
||||
<jackson.databind.version>2.8.8</jackson.databind.version>
|
||||
<jackson.mapper.asl.version>1.9.13</jackson.mapper.asl.version>
|
||||
<wildfly.version>1.5.2.Final</wildfly.version>
|
||||
<aliyun.sdk.version>4.0.3</aliyun.sdk.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-bootstrap</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-context</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- tk-mybatis -->
|
||||
<dependency>
|
||||
<groupId>tk.mybatis</groupId>
|
||||
<artifactId>mapper-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- mybatis -->
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- page-helper -->
|
||||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- hutool -->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- lombok -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- fastjson -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- redis -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>io.lettuce</groupId>
|
||||
<artifactId>lettuce-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- druid-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid</artifactId>
|
||||
<version>${druid.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- thumbnailator -->
|
||||
<dependency>
|
||||
<groupId>net.coobird</groupId>
|
||||
<artifactId>thumbnailator</artifactId>
|
||||
<version>${thumbnailator.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- mysql -->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>${mysql.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--JsonFormat-->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson.databind.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-mapper-asl</artifactId>
|
||||
<version>${jackson.mapper.asl.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- wildfly -->
|
||||
<dependency>
|
||||
<groupId>org.wildfly.common</groupId>
|
||||
<artifactId>wildfly-common</artifactId>
|
||||
<version>${wildfly.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 阿里云短信 -->
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>aliyun-java-sdk-core</artifactId>
|
||||
<version>${aliyun.sdk.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@ -0,0 +1,11 @@
|
||||
package cn.crtech.cloud.common.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Documented // 文档
|
||||
@Retention(RetentionPolicy.RUNTIME) // 在运行时可以获取
|
||||
@Target({ ElementType.FIELD, ElementType.TYPE }) // 作用到字段上
|
||||
public @interface DataExportAnnotation {
|
||||
//导出字段名称
|
||||
String value() default "";
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package cn.crtech.cloud.common.api;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* 阿里云模板配置
|
||||
*/
|
||||
public enum ALiYunSMSEnum {
|
||||
SMS_133972087("SECTION_CHECK_IN_CODE");
|
||||
|
||||
private String typeCode;
|
||||
|
||||
public String getTypeCode() {
|
||||
return typeCode;
|
||||
}
|
||||
|
||||
public void setTypeCode(String typeCode) {
|
||||
this.typeCode = typeCode;
|
||||
}
|
||||
|
||||
ALiYunSMSEnum(String typeCode) {
|
||||
this.typeCode = typeCode;
|
||||
}
|
||||
|
||||
public static ALiYunSMSEnum getEnumValue(String typeCode) {
|
||||
if (!StringUtils.isEmpty(typeCode)) {
|
||||
for (ALiYunSMSEnum sendCodeEnum : ALiYunSMSEnum.values()) {
|
||||
if (sendCodeEnum.getTypeCode().equals(typeCode)) {
|
||||
return sendCodeEnum;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,123 @@
|
||||
package cn.crtech.cloud.common.api;
|
||||
|
||||
/**
|
||||
* 通用返回对象
|
||||
*/
|
||||
public class CommonResult<T> {
|
||||
private long code;
|
||||
private String message;
|
||||
private T data;
|
||||
|
||||
protected CommonResult() {
|
||||
}
|
||||
|
||||
protected CommonResult(long code, String message, T data) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功返回结果
|
||||
*
|
||||
* @param data 获取的数据
|
||||
*/
|
||||
public static <T> CommonResult<T> success(T data) {
|
||||
return new CommonResult<T>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMessage(), data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功返回结果
|
||||
*
|
||||
* @param data 获取的数据
|
||||
* @param message 提示信息
|
||||
*/
|
||||
public static <T> CommonResult<T> success(T data, String message) {
|
||||
return new CommonResult<T>(ResultCode.SUCCESS.getCode(), message, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败返回结果
|
||||
* @param errorCode 错误码
|
||||
*/
|
||||
public static <T> CommonResult<T> failed(IErrorCode errorCode) {
|
||||
return new CommonResult<T>(errorCode.getCode(), errorCode.getMessage(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败返回结果
|
||||
* @param errorCode 错误码
|
||||
* @param message 错误信息
|
||||
*/
|
||||
public static <T> CommonResult<T> failed(IErrorCode errorCode, String message) {
|
||||
return new CommonResult<T>(errorCode.getCode(), message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败返回结果
|
||||
* @param message 提示信息
|
||||
*/
|
||||
public static <T> CommonResult<T> failed(String message) {
|
||||
return new CommonResult<T>(ResultCode.FAILED.getCode(), message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败返回结果
|
||||
*/
|
||||
public static <T> CommonResult<T> failed() {
|
||||
return failed(ResultCode.FAILED);
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数验证失败返回结果
|
||||
*/
|
||||
public static <T> CommonResult<T> validateFailed() {
|
||||
return failed(ResultCode.VALIDATE_FAILED);
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数验证失败返回结果
|
||||
* @param message 提示信息
|
||||
*/
|
||||
public static <T> CommonResult<T> validateFailed(String message) {
|
||||
return new CommonResult<T>(ResultCode.VALIDATE_FAILED.getCode(), message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 未登录返回结果
|
||||
*/
|
||||
public static <T> CommonResult<T> unauthorized(T data) {
|
||||
return new CommonResult<T>(ResultCode.UNAUTHORIZED.getCode(), ResultCode.UNAUTHORIZED.getMessage(), data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 未授权返回结果
|
||||
*/
|
||||
public static <T> CommonResult<T> forbidden(T data) {
|
||||
return new CommonResult<T>(ResultCode.FORBIDDEN.getCode(), ResultCode.FORBIDDEN.getMessage(), data);
|
||||
}
|
||||
|
||||
public long getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(long code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package cn.crtech.cloud.common.api;
|
||||
|
||||
/**
|
||||
* 封装API的错误码
|
||||
*/
|
||||
public interface IErrorCode {
|
||||
long getCode();
|
||||
|
||||
String getMessage();
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package cn.crtech.cloud.common.api;
|
||||
|
||||
/**
|
||||
* 枚举了一些常用API操作码
|
||||
*/
|
||||
public enum ResultCode implements IErrorCode {
|
||||
SUCCESS(200, "操作成功"),
|
||||
FAILED(500, "操作失败"),
|
||||
VALIDATE_FAILED(404, "参数检验失败"),
|
||||
UNAUTHORIZED(401, "暂未登录或token已经过期"),
|
||||
FORBIDDEN(403, "没有相关权限");
|
||||
private long code;
|
||||
private String message;
|
||||
|
||||
private ResultCode(long code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public long getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package cn.crtech.cloud.common.constant;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class AuthConstant {
|
||||
public static final String AUTHORITY_PREFIX = "ROLE_";
|
||||
public static final String AUTHORITY_CLAIM_NAME = "authorities";
|
||||
public static final String APP_SPECIAL_AUTHORITY_SUFFIX = "_Limit_Authority";
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package cn.crtech.cloud.common.constant;
|
||||
|
||||
/**
|
||||
* 消息常量
|
||||
*/
|
||||
public class MessageConstant {
|
||||
public static final String LOGIN_SUCCESS = "登录成功!";
|
||||
public static final String USERNAME_PASSWORD_ERROR = "用户名或密码错误!";
|
||||
public static final String CREDENTIALS_EXPIRED = "该账户的登录凭证已过期,请重新登录!";
|
||||
public static final String ACCOUNT_DISABLED = "该账户已被禁用,请联系管理员!";
|
||||
public static final String ACCOUNT_LOCKED = "该账号已被锁定,请联系管理员!";
|
||||
public static final String ACCOUNT_EXPIRED = "该账号已过期,请联系管理员!";
|
||||
public static final String PERMISSION_DENIED = "没有访问权限,请联系管理员!";
|
||||
public static final String ACCOUNT_SIGNATURE_ERROR = "签名校验失败!";
|
||||
public static final String ACCOUNT_UN_REGISTER = "当前用户未注册!";
|
||||
public static final String ACCOUNT_ERROR = "未查找到当前用户!";
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package cn.crtech.cloud.common.constant;
|
||||
|
||||
/**
|
||||
* Redis常量
|
||||
*/
|
||||
public class RedisConstant {
|
||||
public static final String FREE_SERIES_APP_VERSION = "AUTH:FREE:SERIES:APP:VERSION";
|
||||
public static final String FREE_VERSION_API = "AUTH:FREE_RESOURCE_ROLES_MAP:${SERIESCODE}:${APPCODE}:${VERSION}";
|
||||
public static final String RESOURCE_ROLES_MAP = "AUTH:RESOURCE_ROLES_MAP";
|
||||
public static final String RESOURCE_ADMIN_MAP = "AUTH:RESOURCE_ADMIN_MAP";
|
||||
public static final String DEFAULT_ROLES_MAP = "AUTH:DEDEFAULT_ROLES_MAPFAULT_ROLES_MAP";
|
||||
public static final String CURRENT_USREINFO = "USER:CURRENT_USERINFO:";
|
||||
public static final String CURRENT_WX_USREINFO = "USER:CURRENT_WX_USERINFO:";
|
||||
public static final String LIMIT_AUTHORITY_API_MAP = "AUTH:LIMIT_AUTHORITY_API_MAP";
|
||||
public static final String APP_FEIGN_API_MAP = "AUTH:APP_FEIGN_API_MAP";
|
||||
}
|
||||
86
Common/src/main/java/cn/crtech/cloud/common/dto/Result.java
Normal file
86
Common/src/main/java/cn/crtech/cloud/common/dto/Result.java
Normal file
@ -0,0 +1,86 @@
|
||||
package cn.crtech.cloud.common.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 系统返统一回结果实体类
|
||||
*/
|
||||
public class Result implements Serializable {
|
||||
private String message;
|
||||
|
||||
private Object data;
|
||||
|
||||
private boolean success;
|
||||
|
||||
public Result() {
|
||||
}
|
||||
|
||||
public Result(String message, boolean success) {
|
||||
this.message = message;
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public void setSuccess(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(Object data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public static Result success() {
|
||||
Result result = new Result();
|
||||
result.message = "操作成功";
|
||||
result.success = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Result success(Object data) {
|
||||
Result result = Result.success();
|
||||
result.data = data;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Result success(Object data, String operation) {
|
||||
Result result = Result.success();
|
||||
result.data = data;
|
||||
result.message = operation;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Result error() {
|
||||
Result result = new Result();
|
||||
result.message = "操作失败";
|
||||
result.success = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Result error(Object data) {
|
||||
Result result = Result.error();
|
||||
result.data = data;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Result error(Object data, String operation) {
|
||||
Result result = Result.error();
|
||||
result.data = data;
|
||||
result.message = operation;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
76
Common/src/main/java/cn/crtech/cloud/common/dto/UserDto.java
Normal file
76
Common/src/main/java/cn/crtech/cloud/common/dto/UserDto.java
Normal file
@ -0,0 +1,76 @@
|
||||
package cn.crtech.cloud.common.dto;
|
||||
|
||||
import cn.crtech.cloud.common.annotation.DataExportAnnotation;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Author : yj
|
||||
* Date : 2021-01-14
|
||||
* Description:
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class UserDto {
|
||||
private String companyCode;
|
||||
|
||||
private String companyName;
|
||||
|
||||
private String userName;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private List<String> roles;
|
||||
|
||||
private Boolean companyAdmin;
|
||||
|
||||
@DataExportAnnotation("主键id")
|
||||
private Integer id;
|
||||
|
||||
@DataExportAnnotation("姓名")
|
||||
private String name;
|
||||
|
||||
@DataExportAnnotation("身份证")
|
||||
private String idCard;
|
||||
|
||||
@DataExportAnnotation("昵称")
|
||||
private String nickName;
|
||||
|
||||
@DataExportAnnotation("最后修改人")
|
||||
private Long lastModifier;
|
||||
|
||||
@DataExportAnnotation("最后修时间")
|
||||
private Date lastModifyTime;
|
||||
|
||||
@DataExportAnnotation("状态")
|
||||
private Integer state;
|
||||
|
||||
@DataExportAnnotation("手机号码")
|
||||
private String mobile;
|
||||
|
||||
@DataExportAnnotation("邮箱")
|
||||
private String email;
|
||||
|
||||
@DataExportAnnotation("头像")
|
||||
private String avatar;
|
||||
|
||||
@DataExportAnnotation("密码")
|
||||
private String password;
|
||||
|
||||
@DataExportAnnotation("身份证正面")
|
||||
private String idCardPrev;
|
||||
|
||||
@DataExportAnnotation("身份证反面")
|
||||
private String idCardNext;
|
||||
|
||||
@DataExportAnnotation("真实姓名")
|
||||
private String realName;
|
||||
|
||||
@DataExportAnnotation("注册时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date regTime;
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
package cn.crtech.cloud.common.plugins;
|
||||
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* 自定义日志实体类
|
||||
*/
|
||||
public class Logger {
|
||||
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Logger.class);
|
||||
|
||||
public static void info(String msg) {
|
||||
logger.info(msg);
|
||||
}
|
||||
|
||||
public static void error(String msg) {
|
||||
logger.error(msg);
|
||||
}
|
||||
|
||||
public static void debug(String msg) {
|
||||
info(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化
|
||||
*
|
||||
* @param jsonStr 字符串
|
||||
* @return 返回处理结果
|
||||
*/
|
||||
public static String formatJson(String jsonStr) {
|
||||
if (null == jsonStr || "".equals(jsonStr)) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("\n");
|
||||
char last = '\0';
|
||||
char current = '\0';
|
||||
int indent = 0;
|
||||
for (int i = 0; i < jsonStr.length(); i++) {
|
||||
last = current;
|
||||
current = jsonStr.charAt(i);
|
||||
|
||||
//遇到{ [换行,且下一行缩进
|
||||
switch (current) {
|
||||
case '{':
|
||||
case '[':
|
||||
sb.append(current);
|
||||
sb.append('\n');
|
||||
indent++;
|
||||
addIndentBlank(sb, indent);
|
||||
break;
|
||||
|
||||
//遇到} ]换行,当前行缩进
|
||||
case '}':
|
||||
case ']':
|
||||
sb.append('\n');
|
||||
indent--;
|
||||
addIndentBlank(sb, indent);
|
||||
sb.append(current);
|
||||
break;
|
||||
|
||||
//遇到,换行
|
||||
case ',':
|
||||
sb.append(current);
|
||||
if (last != '\\') {
|
||||
sb.append('\n');
|
||||
addIndentBlank(sb, indent);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sb.append(current);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加space
|
||||
*
|
||||
* @param sb 字符串
|
||||
* @param indent 位置
|
||||
*/
|
||||
private static void addIndentBlank(StringBuilder sb, int indent) {
|
||||
for (int i = 0; i < indent; i++) {
|
||||
sb.append('\t');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
package cn.crtech.cloud.common.plugins;
|
||||
|
||||
import cn.crtech.cloud.common.api.ALiYunSMSEnum;
|
||||
import cn.crtech.cloud.common.utils.SendSMSUtils;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 阿里短信发送工具类
|
||||
*/
|
||||
@Component
|
||||
public class SendMessageService {
|
||||
public Map<String, Object> send(Map<String, Object> map) throws Exception {
|
||||
Map<String, Object> ret = null;
|
||||
if (!map.containsKey("cretch-cloud")) {
|
||||
Logger.info("采用凌凯短信平台发送...");
|
||||
ret = sendHttp(map);
|
||||
} else {
|
||||
Logger.info("采用阿里云平台发送...");
|
||||
ret = sendCloud(map);
|
||||
}
|
||||
Logger.info(JSON.toJSONString(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
private Map<String, Object> sendHttp(Map<String, Object> map) throws Exception {
|
||||
Map<String, Object> resultMap = new HashMap<>();
|
||||
if (!map.containsKey("mobile")) {
|
||||
resultMap.put("success", false);
|
||||
resultMap.put("message", "手机号不能为空!");
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
if (!map.containsKey("content")) {
|
||||
resultMap.put("success", false);
|
||||
resultMap.put("message", "消息内容不能为空!");
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
int success = SendSMSUtils.sendLingKaiSMS(map);
|
||||
if (success > 0) {
|
||||
resultMap.put("success", true);
|
||||
resultMap.put("message", "短信发送成功!");
|
||||
} else {
|
||||
resultMap.put("success", false);
|
||||
resultMap.put("message", "短信服务器出错!");
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
private Map<String, Object> sendCloud(Map<String, Object> map) {
|
||||
Map<String, Object> resultMap = new HashMap<>();
|
||||
if (map.get("mobiles") == null) {
|
||||
resultMap.put("success", false);
|
||||
resultMap.put("message", "手机号不能为空!");
|
||||
return resultMap;
|
||||
} else if (map.get("templateCode") == null) {
|
||||
resultMap.put("success", false);
|
||||
resultMap.put("message", "模版Code不能为空!");
|
||||
return resultMap;
|
||||
} else {
|
||||
String code = map.get("templateCode").toString();
|
||||
ALiYunSMSEnum codeEnum = ALiYunSMSEnum.getEnumValue(code);
|
||||
if (code == null || codeEnum == null) {
|
||||
resultMap.put("success", false);
|
||||
resultMap.put("message", "模版Code错误!");
|
||||
} else {
|
||||
String mobile = map.get("mobile").toString();
|
||||
JSONObject jo = SendSMSUtils.sendALiYunSMS(map, mobile, codeEnum.name());
|
||||
Logger.info(jo.toJSONString());
|
||||
if ("OK".equals(jo.get("Code"))) {
|
||||
resultMap.put("success", true);
|
||||
resultMap.put("message", "短信发送成功!");
|
||||
} else {
|
||||
Logger.info(jo.toJSONString());
|
||||
resultMap.put("success", false);
|
||||
resultMap.put("message", jo.toJSONString());
|
||||
}
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
}
|
||||
}
|
||||
27
Common/src/main/java/cn/crtech/cloud/common/pojo/Tree.java
Normal file
27
Common/src/main/java/cn/crtech/cloud/common/pojo/Tree.java
Normal file
@ -0,0 +1,27 @@
|
||||
package cn.crtech.cloud.common.pojo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.persistence.Transient;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public abstract class Tree<T> {
|
||||
@Transient
|
||||
private Object realId;
|
||||
|
||||
@Transient
|
||||
private Object realParentId;
|
||||
|
||||
@Transient
|
||||
private List<T> children;
|
||||
|
||||
//判断是否根节点
|
||||
public abstract Boolean isRoot();
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package cn.crtech.cloud.common.utils;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class CommonFun {
|
||||
private static long startValue = 0;
|
||||
|
||||
/**
|
||||
* 获取时间戳式的ID值,每秒可取1000个
|
||||
* 长度16位
|
||||
* 格式为:1639 4620 6212 3001 最大为9999 9999 9999 9 999 -》 2286-11-21 01:46:39.999 + 999
|
||||
* @return
|
||||
*/
|
||||
public static synchronized long getSSID() {
|
||||
String id;
|
||||
startValue++;
|
||||
startValue = startValue % 1000;
|
||||
java.text.DecimalFormat format = new java.text.DecimalFormat("000");
|
||||
|
||||
String sStartValue = format.format(startValue);
|
||||
String sDate = String.valueOf(System.currentTimeMillis());
|
||||
id = sDate + sStartValue;
|
||||
return Long.parseLong(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取md5式的ID值
|
||||
* @return
|
||||
*/
|
||||
public static synchronized String getUUID() {
|
||||
String id = UUID.randomUUID().toString();
|
||||
id = id.replaceAll("-", "");
|
||||
id = id.toUpperCase();
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,120 @@
|
||||
package cn.crtech.cloud.common.utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
public class EncryptUtil {
|
||||
protected static final Logger logger = LoggerFactory.getLogger(EncryptUtil.class);
|
||||
|
||||
public EncryptUtil() {
|
||||
}
|
||||
|
||||
public static String parseByte2HexStr(byte[] buf) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
for(int i = 0; i < buf.length; ++i) {
|
||||
String hex = Integer.toHexString(buf[i] & 255);
|
||||
if (hex.length() == 1) {
|
||||
hex = '0' + hex;
|
||||
}
|
||||
|
||||
sb.append(hex.toUpperCase());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static byte[] parseHexStr2Byte(String hexStr) {
|
||||
if (hexStr.length() < 1) {
|
||||
return null;
|
||||
} else {
|
||||
byte[] result = new byte[hexStr.length() / 2];
|
||||
|
||||
for(int i = 0; i < hexStr.length() / 2; ++i) {
|
||||
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
|
||||
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
|
||||
result[i] = (byte)(high * 16 + low);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] decrypt(byte[] content, String password) {
|
||||
try {
|
||||
KeyGenerator kgen = KeyGenerator.getInstance("AES");
|
||||
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
|
||||
secureRandom.setSeed(password.getBytes());
|
||||
kgen.init(128, secureRandom);
|
||||
SecretKey secretKey = kgen.generateKey();
|
||||
byte[] enCodeFormat = secretKey.getEncoded();
|
||||
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
|
||||
Cipher cipher = Cipher.getInstance("AES");
|
||||
cipher.init(2, key);
|
||||
byte[] result = cipher.doFinal(content);
|
||||
return result;
|
||||
} catch (NoSuchAlgorithmException var9) {
|
||||
logger.error(var9.getMessage(), var9);
|
||||
} catch (NoSuchPaddingException var10) {
|
||||
logger.error(var10.getMessage(), var10);
|
||||
} catch (InvalidKeyException var11) {
|
||||
logger.error(var11.getMessage(), var11);
|
||||
} catch (IllegalBlockSizeException var12) {
|
||||
logger.error(var12.getMessage(), var12);
|
||||
} catch (BadPaddingException var13) {
|
||||
logger.error(var13.getMessage(), var13);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static byte[] encrypt(String content, String password) {
|
||||
try {
|
||||
KeyGenerator kgen = KeyGenerator.getInstance("AES");
|
||||
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
|
||||
secureRandom.setSeed(password.getBytes());
|
||||
kgen.init(128, secureRandom);
|
||||
SecretKey secretKey = kgen.generateKey();
|
||||
byte[] enCodeFormat = secretKey.getEncoded();
|
||||
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
|
||||
Cipher cipher = Cipher.getInstance("AES");
|
||||
byte[] byteContent = content.getBytes("utf-8");
|
||||
cipher.init(1, key);
|
||||
byte[] result = cipher.doFinal(byteContent);
|
||||
return result;
|
||||
} catch (NoSuchAlgorithmException var10) {
|
||||
logger.error(var10.getMessage(), var10);
|
||||
} catch (NoSuchPaddingException var11) {
|
||||
logger.error(var11.getMessage(), var11);
|
||||
} catch (InvalidKeyException var12) {
|
||||
logger.error(var12.getMessage(), var12);
|
||||
} catch (UnsupportedEncodingException var13) {
|
||||
logger.error(var13.getMessage(), var13);
|
||||
} catch (IllegalBlockSizeException var14) {
|
||||
logger.error(var14.getMessage(), var14);
|
||||
} catch (BadPaddingException var15) {
|
||||
logger.error(var15.getMessage(), var15);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String content = "www.server41.com";
|
||||
String password = "THIS SHALL NOT BE SEEN.";
|
||||
System.out.println("加密前:" + content);
|
||||
byte[] encryptResult = encrypt(content, password);
|
||||
String encryptResultStr = parseByte2HexStr(encryptResult);
|
||||
System.out.println("加密后:" + encryptResultStr);
|
||||
byte[] decryptFrom = parseHexStr2Byte(encryptResultStr);
|
||||
byte[] decryptResult = decrypt(decryptFrom, password);
|
||||
System.out.println("解密后:" + new String(decryptResult));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package cn.crtech.cloud.common.utils;
|
||||
|
||||
import tk.mybatis.mapper.genid.GenId;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class IDGenerator implements GenId<String> {
|
||||
@Override
|
||||
public String genId(String s, String s1) {
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,59 @@
|
||||
package cn.crtech.cloud.common.utils;
|
||||
|
||||
import cn.crtech.cloud.common.pojo.Tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* author 墨衣
|
||||
* date 2022/3/31
|
||||
* descript
|
||||
**/
|
||||
public class OrganizeTree<T extends Tree> {
|
||||
private List<T> treeList;
|
||||
|
||||
public OrganizeTree(List<T> treeList) {
|
||||
this.treeList = treeList;
|
||||
}
|
||||
|
||||
//建立树形结构
|
||||
public List<T> buildTree() {
|
||||
List<T> tree = new ArrayList<>();
|
||||
for (T node : getRootNode()) {
|
||||
node = buildChildTree(node);
|
||||
tree.add(node);
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
//递归,建立子树形结构
|
||||
private T buildChildTree(T pNode) {
|
||||
List<T> child = new ArrayList<>();
|
||||
for (T node : treeList) {
|
||||
//pNode的id必定存在,node可能存在,可能为null
|
||||
String parentId = node.getRealParentId() == null ? "" : node.getRealParentId().toString();
|
||||
if (pNode.getRealId().toString().equals(parentId)) {
|
||||
child.add(buildChildTree(node));
|
||||
}
|
||||
}
|
||||
if (child.size() != 0) {
|
||||
pNode.setChildren(child);
|
||||
} else {
|
||||
pNode.setChildren(null);
|
||||
}
|
||||
|
||||
return pNode;
|
||||
}
|
||||
|
||||
//获取根节点
|
||||
private List<T> getRootNode() {
|
||||
List<T> root = new ArrayList<>();
|
||||
for (T node : treeList) {
|
||||
if (node.isRoot()) {
|
||||
root.add(node);
|
||||
}
|
||||
}
|
||||
return root;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,112 @@
|
||||
package cn.crtech.cloud.common.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.aliyuncs.CommonRequest;
|
||||
import com.aliyuncs.CommonResponse;
|
||||
import com.aliyuncs.DefaultAcsClient;
|
||||
import com.aliyuncs.IAcsClient;
|
||||
import com.aliyuncs.http.MethodType;
|
||||
import com.aliyuncs.profile.DefaultProfile;
|
||||
import jdk.nashorn.internal.runtime.logging.DebugLogger;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Map;
|
||||
|
||||
public class SendSMSUtils {
|
||||
private static final Logger logger = LoggerFactory.getLogger(DebugLogger.class);
|
||||
private static final SendSMSUtils ourInstance = new SendSMSUtils();
|
||||
|
||||
public static SendSMSUtils getInstance() {
|
||||
return ourInstance;
|
||||
}
|
||||
|
||||
private SendSMSUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param map 模板参数
|
||||
* @param mobiles 手机号码
|
||||
* @param templateCode 模板code
|
||||
* signName
|
||||
* accessKeySecret
|
||||
* accessKeyId
|
||||
* domain
|
||||
* @return 返回处理结果
|
||||
*/
|
||||
public static JSONObject sendALiYunSMS(Map<String, Object> map, String mobiles, String templateCode) {
|
||||
|
||||
String accessKeyId = map.get("accessKeyId").toString();
|
||||
String accessKeySecret = map.get("accessKeySecret").toString();
|
||||
String signName = map.get("signName").toString();
|
||||
String domain = map.get("domain").toString();
|
||||
|
||||
DefaultProfile profile = DefaultProfile.getProfile("default", accessKeyId, accessKeySecret);
|
||||
IAcsClient client = new DefaultAcsClient(profile);
|
||||
|
||||
CommonRequest request = new CommonRequest();
|
||||
request.setMethod(MethodType.POST);
|
||||
request.setDomain(domain);
|
||||
request.setVersion("2017-05-25");
|
||||
request.setAction("SendSms");
|
||||
request.putQueryParameter("PhoneNumbers", mobiles);
|
||||
request.putQueryParameter("SignName", signName);
|
||||
request.putQueryParameter("TemplateCode", templateCode);
|
||||
//移除以下两个不必要的参数
|
||||
map.remove("templateCode");
|
||||
map.remove("platform");
|
||||
String str = JSONObject.toJSONString(map);
|
||||
logger.info("发文:" + str);
|
||||
request.putQueryParameter("TemplateParam", str);
|
||||
JSONObject jo = null;
|
||||
try {
|
||||
CommonResponse response = client.getCommonResponse(request);
|
||||
logger.info(response.getData());
|
||||
jo = JSON.parseObject(response.getData());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
logger.info("返回:" + jo);
|
||||
return jo;
|
||||
}
|
||||
|
||||
/**
|
||||
* int > 0 发送成功!
|
||||
*
|
||||
* mobile 手机号码
|
||||
* content 内容
|
||||
* pwd lingKai配置
|
||||
* domain
|
||||
* corpId
|
||||
*
|
||||
* @return 返回处理结果
|
||||
* @throws Exception 发送异常
|
||||
*/
|
||||
public static int sendLingKaiSMS(Map<String, Object> map) throws Exception {
|
||||
String mobile = map.get("mobile").toString();
|
||||
String content = map.get("content").toString();
|
||||
String corpId = map.get("corpId").toString();
|
||||
String pwd = map.get("pwd").toString();
|
||||
String domain = map.get("domain").toString();
|
||||
|
||||
String send_content = URLEncoder.encode(content, "GB2312");
|
||||
URL url = new URL(domain + "?CorpID=" + corpId + "&Pwd=" + pwd + "&Mobile=" + mobile + "&Content=" + send_content);
|
||||
BufferedReader in;
|
||||
int inputLine = 0;
|
||||
try {
|
||||
logger.info("开始发送短信手机号码为:" + mobile);
|
||||
in = new BufferedReader(new InputStreamReader(url.openStream()));
|
||||
inputLine = new Integer(in.readLine());
|
||||
} catch (Exception e) {
|
||||
logger.info("网络异常,发送短信失败!");
|
||||
inputLine = -2;
|
||||
}
|
||||
logger.info("发送成功!");
|
||||
return inputLine;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,409 @@
|
||||
package cn.crtech.cloud.common.utils;
|
||||
|
||||
import net.coobird.thumbnailator.Thumbnails;
|
||||
import net.coobird.thumbnailator.geometry.Coordinate;
|
||||
import net.coobird.thumbnailator.geometry.Position;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Author : yj
|
||||
* Date : 2021-03-29
|
||||
* Description:
|
||||
*/
|
||||
public class ThumbnailatorUtil {
|
||||
/**
|
||||
* 图片尺寸不变,压缩图片文件大小
|
||||
*
|
||||
* @param bytes 图片文件二进制流
|
||||
* @param imageType 图片格式
|
||||
* @param quality 质量因子 1为最高质量
|
||||
* @return
|
||||
*/
|
||||
public static byte[] compressImage(byte[] bytes, String imageType, float quality) {
|
||||
InputStream in = null;
|
||||
ByteArrayOutputStream bout = null;
|
||||
try {
|
||||
in = new ByteArrayInputStream(bytes);
|
||||
bout = new ByteArrayOutputStream(1024);
|
||||
|
||||
// 图片尺寸不变,压缩图片文件大小outputQuality实现,参数1为最高质量
|
||||
Thumbnails.of(in).scale(1f).outputFormat(imageType).outputQuality(quality).toOutputStream(bout);
|
||||
|
||||
byte[] compressiondata = bout.toByteArray();
|
||||
|
||||
return compressiondata;
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
} finally {
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
if (bout != null) {
|
||||
bout.close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定宽高压缩图片
|
||||
*
|
||||
* @param bytes 图片文件二进制流
|
||||
* @param width 压缩宽度
|
||||
* @param height 压缩高度
|
||||
* @return
|
||||
*/
|
||||
public static byte[] compressImageWithWH(byte[] bytes, int width, int height) {
|
||||
InputStream in = null;
|
||||
ByteArrayOutputStream bout = null;
|
||||
try {
|
||||
in = new ByteArrayInputStream(bytes);
|
||||
bout = new ByteArrayOutputStream(1024);
|
||||
|
||||
Thumbnails.of(in).size(width, height).toOutputStream(bout);
|
||||
|
||||
return bout.toByteArray();
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
} finally {
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
if (bout != null) {
|
||||
bout.close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据比列压缩图片
|
||||
*
|
||||
* @param bytes
|
||||
* @param scale
|
||||
* @return
|
||||
*/
|
||||
public static byte[] compressImageWithScale(byte[] bytes, double scale) {
|
||||
InputStream in = null;
|
||||
ByteArrayOutputStream bout = null;
|
||||
try {
|
||||
in = new ByteArrayInputStream(bytes);
|
||||
bout = new ByteArrayOutputStream(1024);
|
||||
|
||||
Thumbnails.of(in).scale(scale).toOutputStream(bout);
|
||||
|
||||
return bout.toByteArray();
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
} finally {
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
if (bout != null) {
|
||||
bout.close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换图片格式
|
||||
*
|
||||
* @param bytes 源图片文件流
|
||||
* @param toformatImageType 转换后图片格式
|
||||
* @return
|
||||
*/
|
||||
public static byte[] formatImage(byte[] bytes, String toformatImageType, int width, int height) {
|
||||
InputStream in = null;
|
||||
ByteArrayOutputStream bout = null;
|
||||
try {
|
||||
in = new ByteArrayInputStream(bytes);
|
||||
bout = new ByteArrayOutputStream(1024);
|
||||
|
||||
Thumbnails.of(in).size(width, height).outputFormat(toformatImageType).toOutputStream(bout);
|
||||
|
||||
return bout.toByteArray();
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
} finally {
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
if (bout != null) {
|
||||
bout.close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据坐标裁剪图片
|
||||
*
|
||||
* @param bytes 源图片文件流
|
||||
* @param x 起始x坐标
|
||||
* @param y 起始y坐标
|
||||
* @param x1 结束x坐标
|
||||
* @param y1 结束y坐标
|
||||
* @param keepAspectRatio 默认是按照比例缩放的,值为false 时不按比例缩放
|
||||
* @return
|
||||
*/
|
||||
public static byte[] cutImage(byte[] bytes, int x, int y, int x1, int y1, boolean keepAspectRatio) {
|
||||
InputStream in = null;
|
||||
ByteArrayOutputStream bout = null;
|
||||
try {
|
||||
in = new ByteArrayInputStream(bytes);
|
||||
bout = new ByteArrayOutputStream(1024);
|
||||
|
||||
int width = x1 - x;
|
||||
int height = y1 - y;
|
||||
Thumbnails.of(in).sourceRegion(x, y, x1, y1).size(width, height).keepAspectRatio(keepAspectRatio).toOutputStream(bout);
|
||||
|
||||
return bout.toByteArray();
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
} finally {
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
if (bout != null) {
|
||||
bout.close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加图片水印
|
||||
*
|
||||
* @param bytes 源图片文件流
|
||||
* @param width 宽度
|
||||
* @param height 高度
|
||||
* @param position 位置 Positions.BOTTOM_RIGHT
|
||||
* @param watermark 水印图片地址
|
||||
* @param opacity 透明度 0.5f
|
||||
* @param quality 图片质量 0.8f
|
||||
* @return
|
||||
*/
|
||||
public static byte[] addImageWater(byte[] bytes, int width, int height, Position position, String watermark, float opacity, float quality) {
|
||||
InputStream in = null;
|
||||
ByteArrayOutputStream bout = null;
|
||||
try {
|
||||
in = new ByteArrayInputStream(bytes);
|
||||
bout = new ByteArrayOutputStream(1024);
|
||||
|
||||
Thumbnails.of(in)
|
||||
.size(width, height)
|
||||
// 加水印 参数:1.水印位置 2.水印图片 3.不透明度0.0-1.0
|
||||
.watermark(position, ImageIO.read(new File(watermark)), opacity)
|
||||
.outputQuality(quality)
|
||||
.toOutputStream(bout);
|
||||
|
||||
return bout.toByteArray();
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
} finally {
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
if (bout != null) {
|
||||
bout.close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加文字水印
|
||||
*
|
||||
* @param bytes
|
||||
* @param position
|
||||
* @param waterText
|
||||
* @param rotate
|
||||
* @param opacity
|
||||
* @param quality
|
||||
* @return
|
||||
*/
|
||||
public static byte[] addTextWater(byte[] bytes, Position position, String waterText, double rotate, float opacity, float quality) {
|
||||
InputStream in = null;
|
||||
ByteArrayOutputStream bout = null;
|
||||
try {
|
||||
in = new ByteArrayInputStream(bytes);
|
||||
bout = new ByteArrayOutputStream(1024);
|
||||
|
||||
// 设置480x160的大小区域显示水印文本
|
||||
BufferedImage bi = new BufferedImage(480, 160, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g = bi.createGraphics();
|
||||
|
||||
// 设置绘图区域透明
|
||||
bi = g.getDeviceConfiguration().createCompatibleImage(480, 160, Transparency.TRANSLUCENT);
|
||||
g.dispose();
|
||||
g = bi.createGraphics();
|
||||
|
||||
// 设置字体类型、大小、加粗、颜色
|
||||
g.setFont(new Font("微软雅黑", Font.BOLD, 32));
|
||||
g.setColor(new Color(0, 0, 0));
|
||||
char[] data = waterText.toCharArray();
|
||||
// 设置文本显示坐标(0,80)
|
||||
g.drawChars(data, 0, data.length, 0, 80);
|
||||
g.dispose();
|
||||
|
||||
Thumbnails.of(in).scale(1).watermark(position, bi, opacity).outputQuality(quality).toOutputStream(bout);
|
||||
|
||||
return bout.toByteArray();
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
} finally {
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
if (bout != null) {
|
||||
bout.close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 整屏添加文字水印
|
||||
*
|
||||
* @param bytes 源图片二进制流
|
||||
* @param width 图片宽度
|
||||
* @param height 图片高度
|
||||
* @param intervalWidth 间隔宽度
|
||||
* @param intervalHeight 间隔高度
|
||||
* @param waterTextList 水印内容列表
|
||||
* @param fontSize 文字大小
|
||||
* @param opacity 透明度
|
||||
* @param quality 质量
|
||||
* @return
|
||||
*/
|
||||
public static byte[] addTextWaterFullScreen(byte[] bytes, int width, int height, int intervalWidth, int intervalHeight, List<String> waterTextList, int fontSize, float opacity, float quality) {
|
||||
InputStream in = null;
|
||||
ByteArrayOutputStream bout = null;
|
||||
try {
|
||||
in = new ByteArrayInputStream(bytes);
|
||||
bout = new ByteArrayOutputStream(1024);
|
||||
|
||||
// 设置图片大小区域显示水印文本
|
||||
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
// 创建一个Graphics2D的对象
|
||||
Graphics2D g = bi.createGraphics();
|
||||
|
||||
// 设置绘图区域透明,即背景透明
|
||||
bi = g.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
|
||||
g.dispose();
|
||||
g = bi.createGraphics();
|
||||
|
||||
// 设置字体类型,加粗,字体大小
|
||||
Font font = new Font("微软雅黑", Font.BOLD, fontSize);
|
||||
g.setFont(font);
|
||||
// 旋转角度(单位:弧度),以圆点(0,0)为圆心,正代表顺时针,负代表逆时针
|
||||
g.rotate(Math.toRadians(-30), 0, 0);
|
||||
// 设置字体颜色
|
||||
g.setColor(new Color(0, 0, 0));
|
||||
int distance = fontSize + 12;
|
||||
int size = waterTextList.size();
|
||||
// 设置文字字体显示坐标位置
|
||||
for (int i = 0; i < size; i++) {
|
||||
char[] data = waterTextList.get(i).toCharArray();
|
||||
g.drawChars(data, 0, data.length, 0, height / 2 + i * distance);
|
||||
}
|
||||
g.dispose();
|
||||
|
||||
Thumbnails.Builder<? extends InputStream> builder = Thumbnails.of(in).scale(1);
|
||||
|
||||
// 添加文字水印
|
||||
int wMod = (int) Math.ceil(width / intervalWidth);
|
||||
int hMod = (int) Math.ceil(height / intervalHeight);
|
||||
for (int i = 0; i <= wMod; i++) {
|
||||
for (int j = 0; j <= hMod; j++) {
|
||||
int x = (i) * intervalWidth - intervalWidth / 2;
|
||||
int y = (j) * intervalHeight - intervalHeight / 2;
|
||||
System.out.println(x + "," + y);
|
||||
builder.watermark(new Coordinate(x, y), bi, opacity);
|
||||
}
|
||||
}
|
||||
|
||||
builder.outputQuality(quality).toOutputStream(bout);
|
||||
|
||||
return bout.toByteArray();
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
} finally {
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
if (bout != null) {
|
||||
bout.close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 旋转 ,正数:顺时针 负数:逆时针
|
||||
*
|
||||
* @param bytes 源图片文件流
|
||||
* @param width 宽
|
||||
* @param height 高
|
||||
* @param rotate 角度
|
||||
*/
|
||||
public static byte[] rotateImage(byte[] bytes, int width, int height, double rotate) {
|
||||
InputStream in = null;
|
||||
ByteArrayOutputStream bout = null;
|
||||
try {
|
||||
in = new ByteArrayInputStream(bytes);
|
||||
bout = new ByteArrayOutputStream(1024);
|
||||
|
||||
Thumbnails.of(in).size(width, height).rotate(rotate).toOutputStream(bout);
|
||||
|
||||
return bout.toByteArray();
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
} finally {
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
if (bout != null) {
|
||||
bout.close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2858
Dependencies/pom.xml
vendored
Normal file
2858
Dependencies/pom.xml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
0
Documents/01 立项/保存立项相关文档
Normal file
0
Documents/01 立项/保存立项相关文档
Normal file
0
Documents/02 需求/保存需求相关文档
Normal file
0
Documents/02 需求/保存需求相关文档
Normal file
0
Documents/03 设计/保存设计相关文档
Normal file
0
Documents/03 设计/保存设计相关文档
Normal file
0
Documents/04 测试/保存测试相关文档
Normal file
0
Documents/04 测试/保存测试相关文档
Normal file
0
Documents/05 实施/保存实施相关文档
Normal file
0
Documents/05 实施/保存实施相关文档
Normal file
0
Documents/06 用户/保存用户相关文档
Normal file
0
Documents/06 用户/保存用户相关文档
Normal file
111
Feign/pom.xml
Normal file
111
Feign/pom.xml
Normal file
@ -0,0 +1,111 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
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>cn.crtech.cloud.feign</groupId>
|
||||
<artifactId>Feign</artifactId>
|
||||
<version>1.0.1</version>
|
||||
|
||||
<!-- 父工程 -->
|
||||
<parent>
|
||||
<groupId>cn.crtech.cloud.dependencies</groupId>
|
||||
<artifactId>Dependencies</artifactId>
|
||||
<version>1.0.1</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<!-- 依赖的版本锁定 -->
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<java.version>1.8</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
|
||||
<common.version>1.0.1</common.version>
|
||||
<feign.version>10.7.4</feign.version>
|
||||
<httpclient.version>4.5.10</httpclient.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- nacos 客户端-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--提供健康信息接口供监控使用-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.lettuce</groupId>
|
||||
<artifactId>lettuce-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>${httpclient.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-httpclient</artifactId>
|
||||
<version>${feign.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.crtech.cloud.common</groupId>
|
||||
<artifactId>Common</artifactId>
|
||||
<version>${common.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<fork>true</fork>
|
||||
<jvmArguments>-Dfile.encoding=UTF-8</jvmArguments>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
18
Feign/src/main/java/cn/crtech/feign/FeignApplication.java
Normal file
18
Feign/src/main/java/cn/crtech/feign/FeignApplication.java
Normal file
@ -0,0 +1,18 @@
|
||||
package cn.crtech.feign;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
|
||||
@EnableDiscoveryClient
|
||||
@EnableFeignClients(basePackages = "cn.crtech.feign")
|
||||
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, RedisAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class})
|
||||
public class FeignApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(FeignApplication.class, args);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package cn.crtech.feign.config;
|
||||
|
||||
import feign.Logger;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class FeignConfiguration {
|
||||
// 日志级别
|
||||
@Bean
|
||||
Logger.Level feignLoggerLevel() {
|
||||
return Logger.Level.FULL;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
package cn.crtech.feign.config;
|
||||
|
||||
import feign.RequestInterceptor;
|
||||
import feign.RequestTemplate;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class GetHeaderConfiguration {
|
||||
private static final String X_REQUEST_ID = "Bearer ";
|
||||
|
||||
@Bean("requestInterceptor")
|
||||
public RequestInterceptor requestInterceptor() {
|
||||
return new RequestInterceptor() {
|
||||
@Override
|
||||
public void apply(RequestTemplate template) {
|
||||
|
||||
HttpServletRequest httpServletRequest = getHttpServletRequest();
|
||||
|
||||
if (httpServletRequest != null) {
|
||||
//获取头信息
|
||||
Map<String, String> headers = getHeaders(httpServletRequest);
|
||||
// 传递所有请求头,防止部分丢失
|
||||
|
||||
//将请求的头信息放入到RequestTemplate 的头信息中,当使用RequestTemplate发起请求时会自动添加头信息
|
||||
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
||||
template.header(entry.getKey(), entry.getValue());
|
||||
}
|
||||
// 微服务之间传递的唯一标识,区分大小写所以通过httpServletRequest获取
|
||||
if (httpServletRequest.getHeader(X_REQUEST_ID) == null) {
|
||||
template.header(X_REQUEST_ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RequestContextHolder 中获取 HttpServletRequest对象
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private HttpServletRequest getHttpServletRequest() {
|
||||
try {
|
||||
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取头信息
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
private Map<String, String> getHeaders(HttpServletRequest request) {
|
||||
Map<String, String> map = new LinkedHashMap<>();
|
||||
Enumeration<String> enumeration = request.getHeaderNames();
|
||||
if (enumeration != null) {
|
||||
while (enumeration.hasMoreElements()) {
|
||||
String key = enumeration.nextElement();
|
||||
String value = request.getHeader(key);
|
||||
map.put(key, value);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
32
Feign/src/main/java/cn/crtech/feign/controller/AcctApi.java
Normal file
32
Feign/src/main/java/cn/crtech/feign/controller/AcctApi.java
Normal file
@ -0,0 +1,32 @@
|
||||
package cn.crtech.feign.controller;
|
||||
|
||||
import cn.crtech.cloud.common.dto.Result;
|
||||
import cn.crtech.feign.pojo.AccountFlow;
|
||||
import cn.crtech.feign.pojo.CompanyAccount;
|
||||
import cn.crtech.feign.service.AcctClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class AcctApi {
|
||||
@Autowired
|
||||
private AcctClient acctClient;
|
||||
|
||||
@PostMapping("/acct/account/flow")
|
||||
public Result accountFlowCreate(@RequestBody AccountFlow accountFlow) {
|
||||
return acctClient.accountFlowCreate(accountFlow);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/acct/companyAccount/insertCompanyAccount")
|
||||
public Result insertCompanyAccount(@RequestBody CompanyAccount companyAccount) {
|
||||
return acctClient.insertCompanyAccount(companyAccount);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/acct/companyAccount/updateCompanyAccount")
|
||||
public Result updateCompanyAccount(@RequestBody CompanyAccount companyAccount) {
|
||||
return acctClient.updateCompanyAccount(companyAccount);
|
||||
}
|
||||
}
|
||||
34
Feign/src/main/java/cn/crtech/feign/controller/AuthApi.java
Normal file
34
Feign/src/main/java/cn/crtech/feign/controller/AuthApi.java
Normal file
@ -0,0 +1,34 @@
|
||||
package cn.crtech.feign.controller;
|
||||
|
||||
import cn.crtech.cloud.common.dto.Result;
|
||||
import cn.crtech.feign.service.AuthClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* auth模块服务间调用Api
|
||||
*
|
||||
* @author TYP
|
||||
* @since 2023-08-11 14:44
|
||||
*/
|
||||
|
||||
@RestController
|
||||
public class AuthApi {
|
||||
private AuthClient authClient;
|
||||
|
||||
@Autowired
|
||||
public AuthApi(AuthClient authClient) {
|
||||
this.authClient = authClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限数据刷新
|
||||
*
|
||||
* @return 返回处理结果
|
||||
*/
|
||||
@PostMapping("/oauth/initRedis")
|
||||
public Result initRedis() {
|
||||
return authClient.initRedis();
|
||||
}
|
||||
}
|
||||
44
Feign/src/main/java/cn/crtech/feign/controller/LsErpApi.java
Normal file
44
Feign/src/main/java/cn/crtech/feign/controller/LsErpApi.java
Normal file
@ -0,0 +1,44 @@
|
||||
package cn.crtech.feign.controller;
|
||||
|
||||
import cn.crtech.cloud.common.dto.Result;
|
||||
import cn.crtech.feign.dto.ChainUserDto;
|
||||
import cn.crtech.feign.service.LsErpClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class LsErpApi {
|
||||
@Autowired
|
||||
private LsErpClient lsErpClient;
|
||||
|
||||
/**
|
||||
* 获取连锁公司选项
|
||||
*
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/ls/erp/loadChainOption")
|
||||
public Result loadChainOption() {
|
||||
try {
|
||||
return lsErpClient.loadChainOption();
|
||||
} catch (Exception e) {
|
||||
return Result.error("查询失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 连锁用户注册
|
||||
*
|
||||
* @param userDto 注册信息对象
|
||||
* @return 返回注册结果
|
||||
*/
|
||||
@PostMapping("/ls/erp/registerUser")
|
||||
public Result registerUser(@RequestBody ChainUserDto userDto) {
|
||||
try {
|
||||
return lsErpClient.registerUser(userDto);
|
||||
} catch (Exception e) {
|
||||
return Result.error("查询失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
87
Feign/src/main/java/cn/crtech/feign/controller/MnsApi.java
Normal file
87
Feign/src/main/java/cn/crtech/feign/controller/MnsApi.java
Normal file
@ -0,0 +1,87 @@
|
||||
package cn.crtech.feign.controller;
|
||||
|
||||
import cn.crtech.cloud.common.dto.Result;
|
||||
import cn.crtech.feign.dto.MessageDto;
|
||||
import cn.crtech.feign.pojo.WxMpMessage;
|
||||
import cn.crtech.feign.service.MnsClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
public class MnsApi {
|
||||
@Autowired
|
||||
private MnsClient mnsClient;
|
||||
|
||||
@PostMapping("/mns/sendSystemMessage")
|
||||
public Result sendSystemMessage(@RequestBody MessageDto message) {
|
||||
return mnsClient.sendSystemMessage(message);
|
||||
}
|
||||
|
||||
@PostMapping("/mns/sendWxMpTempMessage")
|
||||
public Result sendWxMpTempMessage(@RequestBody WxMpMessage wxMpMessage) {
|
||||
return mnsClient.sendWxMpTempMessage(wxMpMessage);
|
||||
}
|
||||
|
||||
@GetMapping("/mns/sendSMS/{type}/{mobile}")
|
||||
public Result sendSystemMessage(@PathVariable("type") String type, @PathVariable("mobile") String mobile) {
|
||||
return mnsClient.sendSMS(type, mobile);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页条件查询系统消息内容
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/mns/systemMessage/listQueryByPage")
|
||||
Result listQueryByPage(Map<String, Object> params) {
|
||||
return mnsClient.listQueryByPage(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新系统消息状态
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回执行结果
|
||||
*/
|
||||
@PostMapping("/mns/systemMessage/updateSystemMessageStatus")
|
||||
Result updateSystemMessageStatus(Map<String, Object> params) {
|
||||
return mnsClient.updateSystemMessageStatus(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询系统消息
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/mns/systemMessage/listByParams")
|
||||
Result listByParams(Map<String, Object> params) {
|
||||
return mnsClient.listByParams(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送(新增)系统消息
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回执行结果
|
||||
*/
|
||||
@PostMapping("/mns/systemMessage/sendPlatForm")
|
||||
Result sendPlatForm(Map<String, Object> params) {
|
||||
return mnsClient.sendPlatForm(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新系统消息
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回执行结果
|
||||
*/
|
||||
@PostMapping("/mns/systemMessage/update")
|
||||
Result update(Map<String, Object> params) {
|
||||
return mnsClient.update(params);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
package cn.crtech.feign.controller;
|
||||
|
||||
import cn.crtech.cloud.common.api.CommonResult;
|
||||
import cn.crtech.cloud.common.dto.Result;
|
||||
import cn.crtech.feign.service.ResourceClient;
|
||||
import feign.Response;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Controller
|
||||
public class ResourceApi {
|
||||
@Autowired
|
||||
private ResourceClient resourceClient;
|
||||
|
||||
@RequestMapping(value = "/rm/upload", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@ResponseBody
|
||||
public CommonResult addFile(@RequestPart(name = "file") MultipartFile file,
|
||||
@RequestParam(name = "path") String path,
|
||||
@RequestParam(name = "name") String name,
|
||||
@RequestParam(name = "description") String description) {
|
||||
|
||||
return resourceClient.addFile(file, path, name, description);
|
||||
}
|
||||
|
||||
@GetMapping("/rm/s/{fileId}")
|
||||
@ResponseBody
|
||||
public CommonResult showUrl(@PathVariable(value = "fileId") String fileId) {
|
||||
return resourceClient.showUrl(fileId);
|
||||
}
|
||||
|
||||
@PostMapping("/rm/s/much")
|
||||
@ResponseBody
|
||||
public CommonResult showMuchUrl(@RequestBody Map<String, Object> params) {
|
||||
return resourceClient.showMuchUrl(params);
|
||||
}
|
||||
|
||||
@GetMapping("/rm/d/{fileId}")
|
||||
@ResponseBody
|
||||
public CommonResult downloadUrl(@PathVariable(value = "fileId") String fileId) {
|
||||
return resourceClient.downloadUrl(fileId);
|
||||
}
|
||||
|
||||
@PostMapping("/rm/remove")
|
||||
@ResponseBody
|
||||
public CommonResult remove(@RequestBody List<String> fileIds) {
|
||||
return resourceClient.remove(fileIds);
|
||||
}
|
||||
|
||||
@GetMapping("/getFileStream")
|
||||
public Response getFileStream(@RequestParam("fileId")String fileId) {
|
||||
return resourceClient.getFileStream(fileId);
|
||||
}
|
||||
|
||||
@GetMapping(value = {"/rm/byte/res/stream/{fileId}", "/rm/byte/down/stream/{fileId}"}, produces = "application/json;charset=utf-8")
|
||||
@ResponseBody
|
||||
public CommonResult getFileStreamByFileId(@PathVariable("fileId") String fileId) {
|
||||
return resourceClient.getFileStreamByFileId(fileId);
|
||||
}
|
||||
|
||||
@GetMapping("/rm/copyOfMinIoFile")
|
||||
@ResponseBody
|
||||
public Result copyOfMinIoFile(@RequestParam(value = "fileId") String fileId) {
|
||||
return resourceClient.copyOfMinIoFile(fileId);
|
||||
}
|
||||
|
||||
}
|
||||
562
Feign/src/main/java/cn/crtech/feign/controller/UserApi.java
Normal file
562
Feign/src/main/java/cn/crtech/feign/controller/UserApi.java
Normal file
@ -0,0 +1,562 @@
|
||||
package cn.crtech.feign.controller;
|
||||
|
||||
import cn.crtech.cloud.common.dto.Result;
|
||||
import cn.crtech.feign.dto.RegisterDto;
|
||||
import cn.crtech.feign.service.CloudMisClient;
|
||||
import cn.crtech.feign.service.TmClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
public class UserApi {
|
||||
private TmClient tmClient;
|
||||
private CloudMisClient cloudMisClient;
|
||||
|
||||
@Autowired
|
||||
public UserApi(TmClient tmClient, CloudMisClient cloudMisClient) {
|
||||
this.tmClient = tmClient;
|
||||
this.cloudMisClient = cloudMisClient;
|
||||
}
|
||||
|
||||
/************************************* 公司角色 start *******************************************/
|
||||
/**
|
||||
* 条件查询公司角色数据
|
||||
*
|
||||
* @param obj 参数对象
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comRole/loadComRoleByPage")
|
||||
public Result loadComRoleByPage(@RequestBody Map<String, Object> obj) {
|
||||
return cloudMisClient.loadComRoleByPage(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建公司角色数据信息
|
||||
*
|
||||
* @param obj 参数对象
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comRole/createComRole")
|
||||
public Result createComRole(@RequestBody Map<String, Object> obj) {
|
||||
return cloudMisClient.createComRole(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改公司角色数据信息
|
||||
*
|
||||
* @param obj 参数对象
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comRole/updateComRole")
|
||||
public Result updateComRole(@RequestBody Map<String, Object> obj) {
|
||||
return cloudMisClient.updateComRole(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除公司角色
|
||||
*
|
||||
* @param obj 参数对象
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comRole/delComRole")
|
||||
public Result delComRole(@RequestBody Map<String, Object> obj) {
|
||||
return cloudMisClient.delComRole(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 公司角色设定管理员
|
||||
*
|
||||
* @param obj 参数对象
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comRole/setComAdminRole")
|
||||
public Result setComAdminRole(@RequestBody Map<String, Object> obj) {
|
||||
return cloudMisClient.setComAdminRole(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询获取公司已授权绑定的产品数据
|
||||
*
|
||||
* @param obj 参数对象
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comRole/loadComBindSeriesApp")
|
||||
public Result loadComBindSeriesApp(@RequestBody Map<String, Object> obj) {
|
||||
return cloudMisClient.loadComBindSeriesApp(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询获取公司已授权绑定产品的菜单数据
|
||||
*
|
||||
* @param obj 参数对象
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comRole/loadComAppPopedom")
|
||||
public Result loadComAppPopedom(@RequestBody Map<String, Object> obj) {
|
||||
return cloudMisClient.loadComAppPopedom(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询获取公司已授权绑定产品菜单特殊权限数据
|
||||
*
|
||||
* @param obj 参数对象
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comRole/loadComAppPopAuthority")
|
||||
public Result loadComAppPopAuthority(@RequestBody Map<String, Object> obj) {
|
||||
return cloudMisClient.loadComAppPopAuthority(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色绑定授权
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comRole/roleBindAuth")
|
||||
public Result roleBindAuth(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.roleBindAuth(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询角色绑定用户信息
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comRole/loadComRoleUser")
|
||||
public Result loadComRoleUser(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.loadComRoleUser(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色绑定用户信息
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comRole/comRoleBindUser")
|
||||
public Result comRoleBindUser(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.comRoleBindUser(params);
|
||||
}
|
||||
/************************************* 公司角色 end *******************************************/
|
||||
|
||||
/************************************* 授权默认角色 start *******************************************/
|
||||
/**
|
||||
* 条件分页查询企业授权产品默认角色
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/defaultRole/loadComAuthDefaultRoleByPage")
|
||||
Result loadComAuthDefaultRoleByPage(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.loadComAuthDefaultRoleByPage(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询默认角色授权数据
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/defaultRole/loadDefaultRoleAuth")
|
||||
Result loadDefaultRoleAuth(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.loadDefaultRoleAuth(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前角色未绑定用户数据
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/defaultRole/loadUnbindDefaultRoleUser")
|
||||
Result loadUnbindDefaultRoleUser(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.loadUnbindDefaultRoleUser(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色批量绑定用户
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/defaultRole/defaultRoleBindUser")
|
||||
Result defaultRoleBindUser(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.defaultRoleBindUser(params);
|
||||
}
|
||||
/************************************* 授权默认角色 end *******************************************/
|
||||
|
||||
/************************************* 企业用户 start *******************************************/
|
||||
/**
|
||||
* 条件分页查询企业用户信息
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comUser/loadComUserByPage")
|
||||
public Result loadComUserByPage(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.loadComUserByPage(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户注册新增
|
||||
*
|
||||
* @param registerDto 参数对象
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comUser/createComUser")
|
||||
public Result createComUser(@RequestBody Map<String, Object> registerDto) {
|
||||
return cloudMisClient.createComUser(registerDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新企业用户信息
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comUser/updateComUser")
|
||||
public Result updateComUser(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.updateComUser(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业用户状态修改
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comUser/changeComUserState")
|
||||
public Result changeComUserState(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.changeComUserState(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取企业角色内容
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comUser/loadComUserRoleData")
|
||||
public Result loadComUserRoleData(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.loadComUserRoleData(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户绑定角色
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comUser/comUserBindRole")
|
||||
public Result comUserBindRole(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.comUserBindRole(params);
|
||||
}
|
||||
/************************************* 企业用户 end *******************************************/
|
||||
|
||||
/************************************* 企业信息 start *******************************************/
|
||||
/**
|
||||
* 获取企业信息
|
||||
*
|
||||
* @param params 参数对象
|
||||
* <ul>
|
||||
* <li>companyCode: 公司标识</li>
|
||||
* </ul>
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/com/loadComInfo")
|
||||
public Result loadComInfo(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.loadComInfo(params);
|
||||
}
|
||||
/************************************* 企业信息 end *******************************************/
|
||||
|
||||
/************************************* 个人企业 start *******************************************/
|
||||
/**
|
||||
* 修改用户默认企业
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comUser/setDefaultCompany")
|
||||
public Result setDefaultCompany(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.setDefaultCompany(params);
|
||||
}
|
||||
/************************************* 个人企业 end *******************************************/
|
||||
|
||||
/************************************* 个人技能证书 start *******************************************/
|
||||
/**
|
||||
* 用户技能证书提交
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回结果
|
||||
*/
|
||||
@PostMapping("/misFeign/userSkill/uploadCertificate")
|
||||
public Result uploadCertificate(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.uploadCertificate(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询个人技能证书
|
||||
*
|
||||
* @param params 参数对象
|
||||
* <ul>
|
||||
* <li>userId: 用户ID</li>
|
||||
* </ul>
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/userSkill/loadSelfCertificate")
|
||||
public Result loadSelfCertificate(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.loadSelfCertificate(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除个人技能证书
|
||||
*
|
||||
* @param params 参数对象
|
||||
* <ul>
|
||||
* <li>id: 技能内容ID</li>
|
||||
* </ul>
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/userSkill/delSelfCertificate")
|
||||
public Result delSelfCertificate(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.delSelfCertificate(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件获取字典数据信息
|
||||
*
|
||||
* @param params 参数对象
|
||||
* <ul>
|
||||
* <li>typeCode: 字典类型标识</li>
|
||||
* <li>code: 字典数据标识</li>
|
||||
* <li>name: 字典数据名称</li>
|
||||
* </ul>
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/dict/loadDictDataByCondition")
|
||||
public Result loadDictDataByCondition(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.loadDictDataByCondition(params);
|
||||
}
|
||||
/************************************* 个人技能证书 end *******************************************/
|
||||
|
||||
/************************************* 安全中心 start *******************************************/
|
||||
/**
|
||||
* 用户密码修改
|
||||
*
|
||||
* @param obj 参数对象
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/user/updateUserPwd")
|
||||
public Result updateUserPwd(@RequestBody Map<String, Object> obj) {
|
||||
return cloudMisClient.updateUserPwd(obj);
|
||||
}
|
||||
/************************************* 安全中心 end *******************************************/
|
||||
|
||||
/************************************* 个人中心 start *******************************************/
|
||||
/**
|
||||
* 更新用户信息
|
||||
*
|
||||
* @param params 参数对象
|
||||
* <ul>
|
||||
* <li>id: 用户ID</li>
|
||||
* <li>email: 邮箱地址</li>
|
||||
* <li>name: 名称</li>
|
||||
* <li>state: 企业用户状态</li>
|
||||
* </ul>
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/user/renewUserInfo")
|
||||
public Result renewUserInfo(@RequestBody Map<String, Object> params) {
|
||||
try {
|
||||
cloudMisClient.renewUserInfo(params);
|
||||
;
|
||||
tmClient.updateStaffInfo(params);
|
||||
} catch (Exception e) {
|
||||
return Result.error("修改人员失败");
|
||||
}
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取团队管理用户信息
|
||||
*
|
||||
* @param params 参数对象
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/user/staff/queryById")
|
||||
public Result queryStaffById(@RequestBody Map<String, Object> params) {
|
||||
return tmClient.queryStaffById(params);
|
||||
}
|
||||
/************************************* 个人中心 end *******************************************/
|
||||
|
||||
/************************************* 其他调用内容 start **************************************/
|
||||
/**
|
||||
* 条件查询所有满足条件的所有用户数据(产品标识及公司标识)
|
||||
*
|
||||
* @param params 参数对象
|
||||
* <ul>
|
||||
* <li>applicationCode: 产品标识</li>
|
||||
* <li>companyCode: 公司标识</li>
|
||||
* </ul>
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/user/queryAll")
|
||||
public Result queryAllUser(@RequestParam Map<String, Object> params) {
|
||||
return cloudMisClient.queryAllUser(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件查询所有满足条件的所有用户数据(公司标识)
|
||||
*
|
||||
* @param params 参数对象
|
||||
* <ul>
|
||||
* <li>companyCode: 公司标识</li>
|
||||
* </ul>
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/user/queryUserByCompanyCode")
|
||||
public Result queryUserByCompanyCode(@RequestParam Map<String, Object> params) {
|
||||
return cloudMisClient.queryUserByCompanyCode(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据手机号码查询用户信息
|
||||
*
|
||||
* @param mobile 用户手机号码
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/user/queryUserByMobile")
|
||||
public Result queryUserByMobile(@RequestParam String mobile) {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("mobile", mobile);
|
||||
return cloudMisClient.queryUserByMobile(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户端用户注册
|
||||
*
|
||||
* @param user 参数对象
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/user/clientRegister")
|
||||
Result clientRegister(@RequestBody Map<String, Object> user) {
|
||||
return cloudMisClient.clientRegister(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件查询所有满足条件的所有用户数据(角色标识)
|
||||
*
|
||||
* @param params 参数对象
|
||||
* <ul>
|
||||
* <li>pageNum: 分页页码</li>
|
||||
* <li>pageSize: 数据个数</li>
|
||||
* <li>roleCode: 对应角色标识集合</li>
|
||||
* <li>nickName: 用户别名</li>
|
||||
* <li>companyName: 企业名称</li>
|
||||
* <li>mobile: 手机号码</li>
|
||||
* </ul>
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/user/queryUserByRoleCode")
|
||||
Result queryUserByRoleCode(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.queryUserByRoleCode(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询非公司用户
|
||||
*
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/user/queryNotCompanyUser")
|
||||
Result queryNotCompanyUser() {
|
||||
return cloudMisClient.queryNotCompanyUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询已创建的公司医院信息
|
||||
*
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/company/queryHospitalInfo")
|
||||
Result queryHospitalInfo() {
|
||||
return cloudMisClient.queryHospitalInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* 授权数据信息查询
|
||||
*
|
||||
* @param obj 参数对象
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comApp/loadRoleApp")
|
||||
Result loadComAuthApp(@RequestBody Map<String, Object> obj) {
|
||||
return cloudMisClient.loadComAuthApp(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户信息(团队管理)
|
||||
*
|
||||
* @param params 参数对象
|
||||
* <ul>
|
||||
* <li>userName: 用户名称</li>
|
||||
* <li>serialNo: 员工编号</li>
|
||||
* <li>userId: 用户ID</li>
|
||||
* <li>mobile: 手机号码</li>
|
||||
* </ul>
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/user/updateUserInfoByTm")
|
||||
Result updateUserInfoByTm(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.updateUserInfoByTm(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取连锁数据集合
|
||||
*
|
||||
* @param params 参数对象
|
||||
* <ul>
|
||||
* <li>chainName: 连锁名称</li>
|
||||
* <li>chainCode: 连锁标识</li>
|
||||
* <li>mechanismName: 机构名称</li>
|
||||
* <li>mechanismCode: 机构标识</li>
|
||||
* <li>isHeadOffice: 是否连锁总店</li>
|
||||
* <li>isSystemCompany: 是否存在关联公司</li>
|
||||
* </ul>
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/misFeign/chain/getChainList")
|
||||
Result getChainList(@RequestBody Map<String, Object> params) {
|
||||
return cloudMisClient.getChainList(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量新增用户
|
||||
*
|
||||
* @param registerDtos 用户数据集合
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/misFeign/comUser/batchRegister")
|
||||
public Result batchRegister(@RequestBody List<RegisterDto> registerDtos) {
|
||||
return cloudMisClient.batchRegister(registerDtos);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化企业用户团队管理用户信息
|
||||
*
|
||||
* @param objectList 用户信息数据集合
|
||||
* @return 返回操作结果
|
||||
*/
|
||||
@PostMapping("/user/staff/initTMStaff")
|
||||
public Result initTMStaff(@RequestBody List<Map<String, Object>> objectList) {
|
||||
return tmClient.initTMStaff(objectList);
|
||||
}
|
||||
}
|
||||
27
Feign/src/main/java/cn/crtech/feign/dto/ChainUserDto.java
Normal file
27
Feign/src/main/java/cn/crtech/feign/dto/ChainUserDto.java
Normal file
@ -0,0 +1,27 @@
|
||||
package cn.crtech.feign.dto;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 连锁主界面用户注册DTO对象
|
||||
*
|
||||
* @author TYP
|
||||
* @since 2023-02-23 16:18
|
||||
*/
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ChainUserDto implements Serializable {
|
||||
private Integer companyId;
|
||||
private String name;
|
||||
private String mobile;
|
||||
private String email;
|
||||
private String zhiyid;
|
||||
private String lgnname;
|
||||
private String password;
|
||||
}
|
||||
15
Feign/src/main/java/cn/crtech/feign/dto/MessageDto.java
Normal file
15
Feign/src/main/java/cn/crtech/feign/dto/MessageDto.java
Normal file
@ -0,0 +1,15 @@
|
||||
package cn.crtech.feign.dto;
|
||||
|
||||
import cn.crtech.feign.pojo.Message;
|
||||
import cn.crtech.feign.pojo.MessageList;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class MessageDto implements Serializable {
|
||||
private Message message;
|
||||
|
||||
private List<MessageList> messageLists;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user