commit:微服务uaa版本

This commit is contained in:
Jerry
2021-12-21 10:56:30 +08:00
parent 1c126f3188
commit 30ea113bf3
1254 changed files with 217496 additions and 0 deletions

View File

@@ -0,0 +1,80 @@
<?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">
<parent>
<groupId>com.orangeforms</groupId>
<artifactId>uaa</artifactId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>uaa-auth</artifactId>
<version>1.0.0</version>
<name>uaa-auth</name>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.orangeforms</groupId>
<artifactId>common-core</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 2.3.3 之前的版本和redis不兼容 -->
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.8.RELEASE</version>
</dependency>
<!-- redis 分布式session -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-logging</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,20 @@
package com.orangeforms.uaaauth;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.context.annotation.ComponentScan;
/**
* UAA服务启动类。
*
* @author Jerry
* @date 2020-08-08
*/
@SpringCloudApplication
@ComponentScan("com.orangeforms")
public class UaaAuthApplication {
public static void main(String[] args) {
SpringApplication.run(UaaAuthApplication.class, args);
}
}

View File

@@ -0,0 +1,50 @@
package com.orangeforms.uaaauth.config;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import java.io.IOException;
/**
* OAuth2AccessToken 接口对象的专有序列化转换器。如果不指定该转换器并采用缺省的Fastjson
* /oauth/token返回的对象参数格式不符合oauth2的标准。
* 由于OAuth2AccessToken接口对象中的每一个字段都基于jackson指定了不同的序列化方式因此
* 这里我们针对OAuth2AccessToken仍然保留使用jackson的序列化方式。
*
* @author Jerry
* @date 2020-08-08
*/
@SuppressWarnings("NullableProblems")
public class AuthHttpMessageConverter extends AbstractHttpMessageConverter<DefaultOAuth2AccessToken> {
private final MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
public AuthHttpMessageConverter() {
super(MediaType.APPLICATION_JSON);
}
@Override
protected boolean supports(Class<?> clazz) {
return clazz.equals(DefaultOAuth2AccessToken.class);
}
@Override
protected DefaultOAuth2AccessToken readInternal(
Class<? extends DefaultOAuth2AccessToken> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
throw new UnsupportedOperationException(
"This converter is only used for converting DefaultOAuth2AccessToken to json.");
}
@Override
protected void writeInternal(DefaultOAuth2AccessToken accessToken, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
mappingJackson2HttpMessageConverter.write(accessToken, MediaType.APPLICATION_JSON, outputMessage);
}
}

View File

@@ -0,0 +1,26 @@
package com.orangeforms.uaaauth.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
/**
* 为OAuth2AccessToken 接口对象设定专有的序列化转换器。如果不指定该转换器并采用缺省的Fastjson
* /oauth/token返回的对象参数格式不符合oauth2的标准。
* 由于OAuth2AccessToken接口对象中的每一个字段都基于jackson指定了不同的序列化方式因此
* 这里我们针对OAuth2AccessToken仍然保留使用jackson的序列化方式。
*
* @author Jerry
* @date 2020-08-08
*/
@Configuration
public class AuthWebMvcConfig implements WebMvcConfigurer {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
AuthHttpMessageConverter authHttpMessageConverter = new AuthHttpMessageConverter();
converters.add(0, authHttpMessageConverter);
}
}

View File

@@ -0,0 +1,115 @@
package com.orangeforms.uaaauth.config;
import com.orangeforms.uaaauth.service.ClientDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.common.exceptions.*;
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.code.RandomValueAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
import java.util.Collections;
/**
* 认证授权服务配置类。
*
* @author Jerry
* @date 2020-08-08
*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private ClientDetailsServiceImpl clientDetailsService;
@Autowired
private TokenStore tokenStore;
@Autowired
private RandomValueAuthorizationCodeServices authorizationCodeServices;
@Autowired
private WebResponseExceptionTranslator<OAuth2Exception> webResponseExceptionTranslator;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// 将用户对象作为token的附加信息一同返回给应用服务减少一次网络交互。
TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
enhancerChain.setTokenEnhancers(Collections.singletonList(new CustomTokenEnhancer()));
// 配置令牌存储对象这里我们使用了下面的RedisTokenStore
endpoints.tokenStore(tokenStore)
.authenticationManager(authenticationManager)
// 获取用户数据服务该bean的实际类型为UserDetailsServiceImpl。
.userDetailsService(userDetailsService)
// 授权码被存储在Redis该bean的实际类型为RedisAuthorizationCodeServices。
.authorizationCodeServices(authorizationCodeServices)
// 自定义异常处理。
.exceptionTranslator(webResponseExceptionTranslator)
// 扩展token携带的数据在登录验证成功后同时返回了userId以供应用服务使用减少了与uaa-auth的交互次数。
// 该bean的实际类型为CustomTokenEnhancer
.tokenEnhancer(enhancerChain);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
.tokenKeyAccess("isAuthenticated()")
.checkTokenAccess("permitAll()")
// 让/oauth/token支持client_id以及client_secret作表单登录认证
.allowFormAuthenticationForClients();
}
@Bean
public TokenStore tokenStore(RedisConnectionFactory connectionFactory) {
return new RedisTokenStore(connectionFactory);
}
@Bean
public WebResponseExceptionTranslator<OAuth2Exception> webResponseExceptionTranslator() {
return new DefaultWebResponseExceptionTranslator() {
public static final String BAD_MSG = "坏的凭证";
@Override
public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception {
OAuth2Exception oAuth2Exception;
if (e.getMessage() != null && e.getMessage().equals(BAD_MSG)) {
oAuth2Exception = new InvalidGrantException("用户名或密码错误", e);
} else if (e instanceof InternalAuthenticationServiceException) {
oAuth2Exception = new InvalidGrantException(e.getMessage(), e);
} else if (e instanceof RedirectMismatchException) {
oAuth2Exception = new InvalidGrantException(e.getMessage(), e);
} else if (e instanceof InvalidScopeException) {
oAuth2Exception = new InvalidGrantException(e.getMessage(), e);
} else {
oAuth2Exception = new UnsupportedResponseTypeException("服务内部错误", e);
}
ResponseEntity<OAuth2Exception> response = super.translate(oAuth2Exception);
ResponseEntity.status(oAuth2Exception.getHttpErrorCode());
response.getBody().addAdditionalInformation("respCode", oAuth2Exception.getHttpErrorCode() + "");
response.getBody().addAdditionalInformation("respMsg", oAuth2Exception.getMessage());
return response;
}
};
}
}

View File

@@ -0,0 +1,36 @@
package com.orangeforms.uaaauth.config;
import org.springframework.security.core.userdetails.User;
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 java.util.HashMap;
import java.util.Map;
/**
* 自定义访问令牌对象的数据增强器。
* 在/oauth/token接口中仅仅返回最基本的验证数据这里我们通过增强器将username也连同返回
* 其目的主要为两点:
* 1. 避免uaa客户端在获取access_token后再次发出请求获取username提升验证效率。
* 2. 给出一个典型的例子,今后如果需要添加更多的信息,可以直接在这里修改。
*
* @author Jerry
* @date 2020-08-08
*/
public class CustomTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
final Map<String, Object> additionalInfo = new HashMap<>(1);
Object principal = authentication.getPrincipal();
// 增加id参数
if (principal instanceof User) {
User user = (User) principal;
additionalInfo.put("username", user.getUsername());
}
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
}
}

View File

@@ -0,0 +1,30 @@
package com.orangeforms.uaaauth.config;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.mybatis.spring.annotation.MapperScan;
import javax.sql.DataSource;
/**
* 数据源配置Bean对象。
*
* @author Jerry
* @date 2020-08-08
*/
@Configuration
@EnableTransactionManagement
@MapperScan(value = {"com.orangeforms.*.dao", "com.orangeforms.common.*.dao"})
public class DataSourceConfig {
@Bean(initMethod = "init", destroyMethod = "close")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.druid")
public DataSource druidDataSource() {
return DruidDataSourceBuilder.create().build();
}
}

View File

@@ -0,0 +1,135 @@
package com.orangeforms.uaaauth.config;
import com.orangeforms.common.core.constant.ApplicationConstant;
import com.orangeforms.common.core.util.RsaUtil;
import com.orangeforms.uaaauth.handler.AuthLogoutHandler;
import com.orangeforms.uaaauth.handler.AuthLogoutSuccessHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
/**
* 认证授权服务安全配置类。
*
* @author Jerry
* @date 2020-08-08
*/
@Slf4j
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
/**
* 全局用户信息。
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new CustomPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
// login.html位于resources/static目录中用户登录时将使用该页面。
.loginPage("/login.html")
// 登录处理url。在login.html的表单提交中将使用该uri。
.loginProcessingUrl("/uaa/login")
// 注册登录成功后的处理器。
.successHandler(loginSuccessHandler())
.and()
.logout()
// 登出时调用的uri该uri的处理逻辑已在oauth内置的filter中实现。
.logoutUrl("/oauth/remove/token")
// 登出成功处理器
.logoutSuccessHandler(new AuthLogoutSuccessHandler())
// 登出操作处理器。
.addLogoutHandler(authLogoutHandler())
// 登出后清除session。以使用户下次访问授权页面时必须重新进行登录验证。
.clearAuthentication(true)
.and()
.csrf().disable()
// 解决不允许显示在iframe的问题
.headers().frameOptions().disable().cacheControl();
// 授权码模式单独处理需要session的支持此模式可以支持所有oauth2的认证
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
}
/**
* 自定义的密码匹配对象。相比于Spring Security的BCryptPasswordEncoder会现将前端传入
* 的密码进行RSA解密再将解密后的结果交由BCryptPasswordEncoder对象进行密码匹配。
*/
static class CustomPasswordEncoder extends BCryptPasswordEncoder {
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
try {
rawPassword = URLDecoder.decode(rawPassword.toString(), StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
log.error("Failed to call URLDecoder.decode for passwd [" + rawPassword + "]", e);
return false;
}
try {
rawPassword = RsaUtil.decrypt(rawPassword.toString(), ApplicationConstant.PRIVATE_KEY);
} catch (Exception e) {
log.error("Failed to call RsaUtil.decrypt for passwd [" + rawPassword + "]", e);
return false;
}
return super.matches(rawPassword, encodedPassword);
}
}
/**
* 用户认证管理对象。
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* 登出操作处理器。
* @return 登出操作处理器。
*/
@Bean
public AuthLogoutHandler authLogoutHandler() {
return new AuthLogoutHandler();
}
/**
* 登录成功操作处理器。
* @return 登录成功操作处理器。
*/
@Bean
public AuthenticationSuccessHandler loginSuccessHandler() {
return new SavedRequestAwareAuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
super.onAuthenticationSuccess(request, response, authentication);
}
};
}
}

View File

@@ -0,0 +1,73 @@
package com.orangeforms.uaaauth.controller;
import com.orangeforms.uaaauth.model.SysUaaUser;
import com.orangeforms.uaaauth.service.SysUaaUserService;
import com.orangeforms.common.core.constant.ErrorCodeEnum;
import com.orangeforms.common.core.object.ResponseResult;
import com.orangeforms.common.core.util.MyCommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
/**
* UaaUser用户对象查询示例接口。
*
* @author Jerry
* @date 2020-08-08
*/
@Slf4j
@RestController
@RequestMapping("/uaaauth/sysUaaUser")
public class SysUaaUserController {
@Autowired
private SysUaaUserService sysUaaUserService;
@Autowired
private PasswordEncoder passwordEncoder;
/**
* 获取UAA授权用户的相信信息。
* 在Uaa客户端应用正确获取access_token后可通过请求
* /admin/uaa/sysUaaUser/view?username=xxx&access_token=yyy 获取用户的详情信息。
*
* @param username 用户名。
* @return 授权用户的详细信息。
*/
@GetMapping("/view")
public ResponseResult<SysUaaUser> view(@RequestParam String username) {
if (MyCommonUtil.existBlankArgument(username)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
// 这里查看用户数据时候需要把用户多对多关联的角色和数据权限Id一并查出。
SysUaaUser user = sysUaaUserService.getByUsername(username);
if (user == null) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success(user);
}
/**
* 操作员修改自己的密码。
*
* @param username 用户名。
* @param oldPass 原有密码明文。
* @param newPass 新密码明文。
* @return 应答结果对象。
*/
@GetMapping("/changePassword")
public ResponseResult<Void> changePassword(
@RequestParam String username, @RequestParam String oldPass, @RequestParam String newPass) {
if (MyCommonUtil.existBlankArgument(newPass, oldPass)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
SysUaaUser user = sysUaaUserService.getByUsername(username);
if (user == null || !passwordEncoder.matches(oldPass, user.getPassword())) {
return ResponseResult.error(ErrorCodeEnum.INVALID_USERNAME_PASSWORD);
}
if (!sysUaaUserService.changePassword(user.getUserId(), newPass)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success();
}
}

View File

@@ -0,0 +1,13 @@
package com.orangeforms.uaaauth.dao;
import com.orangeforms.common.core.base.dao.BaseDaoMapper;
import com.orangeforms.uaaauth.model.AuthClientDetails;
/**
* UAA应用客户端数据操作访问接口。
*
* @author Jerry
* @date 2020-08-08
*/
public interface AuthClientDetailsMapper extends BaseDaoMapper<AuthClientDetails> {
}

View File

@@ -0,0 +1,13 @@
package com.orangeforms.uaaauth.dao;
import com.orangeforms.uaaauth.model.SysUaaUser;
import com.orangeforms.common.core.base.dao.BaseDaoMapper;
/**
* UAA用户管理数据操作访问接口。
*
* @author Jerry
* @date 2020-08-08
*/
public interface SysUaaUserMapper extends BaseDaoMapper<SysUaaUser> {
}

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.orangeforms.uaaauth.dao.AuthClientDetailsMapper">
<resultMap id="BaseResultMap" type="com.orangeforms.uaaauth.model.AuthClientDetails">
<id column="client_id" jdbcType="VARCHAR" property="clientId"/>
<result column="client_secret" jdbcType="VARCHAR" property="clientSecret"/>
<result column="client_secret_plain" jdbcType="VARCHAR" property="clientSecretPlain"/>
<result column="client_desc" jdbcType="VARCHAR" property="clientDesc"/>
<result column="authorized_grant_types" jdbcType="VARCHAR" property="authorizedGrantTypes"/>
<result column="web_server_redirect_uri" jdbcType="VARCHAR" property="webServerRedirectUri"/>
<result column="access_token_validity" jdbcType="INTEGER" property="accessTokenValidity"/>
<result column="refresh_token_validity" jdbcType="INTEGER" property="refreshTokenValidity"/>
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
<result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="deleted_flag" jdbcType="BIT" property="deletedFlag"/>
</resultMap>
</mapper>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.orangeforms.uaaauth.dao.SysUaaUserMapper">
<resultMap id="BaseResultMap" type="com.orangeforms.uaaauth.model.SysUaaUser">
<id column="user_id" jdbcType="BIGINT" property="userId"/>
<result column="username" jdbcType="VARCHAR" property="username"/>
<result column="password" jdbcType="VARCHAR" property="password"/>
<result column="show_name" jdbcType="VARCHAR" property="showName"/>
<result column="locked" jdbcType="INTEGER" property="locked"/>
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
<result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="deleted_flag" jdbcType="BIT" property="deletedFlag"/>
</resultMap>
</mapper>

View File

@@ -0,0 +1,39 @@
package com.orangeforms.uaaauth.handler;
import com.orangeforms.uaaauth.util.AuthUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 登出操作处理器对象。这里将同时清空redis中的access_token。
*
* @author Jerry
* @date 2020-08-08
*/
@Slf4j
public class AuthLogoutHandler implements LogoutHandler {
@Autowired
private TokenStore tokenStore;
@Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
String token = request.getParameter("token");
if (StringUtils.isBlank(token)) {
token = AuthUtils.extractToken(request);
}
if (StringUtils.isNotBlank(token)) {
OAuth2AccessToken existingAccessToken = tokenStore.readAccessToken(token);
if (existingAccessToken != null) {
tokenStore.removeAccessToken(existingAccessToken);
}
}
}
}

View File

@@ -0,0 +1,49 @@
package com.orangeforms.uaaauth.handler;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.orangeforms.common.core.object.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
/**
* 登出成功处理器对象。
*
* @author Jerry
* @date 2020-08-08
*/
@Slf4j
public class AuthLogoutSuccessHandler implements LogoutSuccessHandler {
private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
@Override
public void onLogoutSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication authentication) throws IOException {
String redirectUri = request.getParameter("redirect_uri");
if (StrUtil.isNotEmpty(redirectUri)) {
// 重定向指定的地址
redirectStrategy.sendRedirect(request, response, redirectUri);
} else {
response.setStatus(HttpStatus.OK.value());
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
PrintWriter writer = response.getWriter();
String jsonStr = JSON.toJSONString(ResponseResult.success("登出成功"));
writer.write(jsonStr);
writer.flush();
}
}
}

View File

@@ -0,0 +1,76 @@
package com.orangeforms.uaaauth.model;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.baomidou.mybatisplus.annotation.*;
import com.orangeforms.common.core.base.model.BaseModel;
/**
* OAuth2 应用客户端表的实体对象。
*
* @author Jerry
* @date 2020-08-08
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName(value = "zz_auth_client_details")
public class AuthClientDetails extends BaseModel {
/**
* 应用标识。
*/
@TableId(value = "client_id")
private String clientId;
/**
* 应用密钥(bcyt) 加密。
*/
@JSONField(serialize = false)
@TableField(value = "client_secret")
private String clientSecret;
/**
* 应用密钥(明文)。
*/
@TableField(value = "client_secret_plain")
private String clientSecretPlain;
/**
* 应用描述。
*/
@TableField(value = "client_desc")
private String clientDesc;
/**
* 5种oauth授权方式(authorization_code,password,refresh_token,client_credentials)。
*/
@TableField(value = "authorized_grant_types")
private String authorizedGrantTypes;
/**
* 回调地址 。
*/
@TableField(value = "web_server_redirect_uri")
private String webServerRedirectUri;
/**
* access_token有效期。
*/
@TableField(value = "access_token_validity")
private Integer accessTokenValidity;
/**
* refresh_token有效期。
*/
@TableField(value = "refresh_token_validity")
private Integer refreshTokenValidity;
/**
* 是否删除(1: 正常,-1 删除)
*/
@JSONField(serialize = false)
@TableLogic
@TableField(value = "deleted_flag")
private Integer deletedFlag;
}

View File

@@ -0,0 +1,62 @@
package com.orangeforms.uaaauth.model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.annotation.*;
import com.orangeforms.common.core.base.model.BaseModel;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* SysUaaUser实体对象。
*
* @author Jerry
* @date 2020-08-08
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName(value = "zz_sys_uaa_user")
public class SysUaaUser extends BaseModel {
/**
* 用户Id。
*/
@NotNull(message = "数据验证失败用户Id不能为空")
@TableId(value = "user_id")
private Long userId;
/**
* 登录用户名。
*/
@NotBlank(message = "数据验证失败,用户名不能为空!")
private String username;
/**
* 用户密码。
*/
@NotBlank(message = "数据验证失败,用户密码不能为空!")
private String password;
/**
* 用户显示名称。
*/
@NotBlank(message = "数据验证失败,用户显示名称不能为空!")
@TableField(value = "show_name")
private String showName;
/**
* 用户状态(0: 正常 1: 锁定)。
*/
@NotNull(message = "数据验证失败,用户状态不能为空!")
private Boolean locked;
/**
* 是否删除(1: 正常,-1 删除)
*/
@JSONField(serialize = false)
@TableLogic
@TableField(value = "deleted_flag")
private Integer deletedFlag;
}

View File

@@ -0,0 +1,55 @@
package com.orangeforms.uaaauth.service;
import com.orangeforms.uaaauth.dao.AuthClientDetailsMapper;
import com.orangeforms.uaaauth.model.AuthClientDetails;
import com.orangeforms.common.core.constant.GlobalDeletedFlag;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.client.BaseClientDetails;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.Collections;
import java.util.stream.Collectors;
/**
* UAA客户端应用数据操作服务类。该类必须为ClientDetailsService接口的实现类。
* loadClientByClientId方法被Oauth2框架调用获取客户端数据。
*
* @author Jerry
* @date 2020-08-08
*/
@Service
public class ClientDetailsServiceImpl implements ClientDetailsService {
@Autowired
private AuthClientDetailsMapper clientDetailsMapper;
@Override
public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
AuthClientDetails authClientDetails = clientDetailsMapper.selectById(clientId);
if (authClientDetails == null || authClientDetails.getDeletedFlag() == GlobalDeletedFlag.DELETED) {
throw new ClientRegistrationException("应用Id不存在");
}
BaseClientDetails clientDetails = new BaseClientDetails();
clientDetails.setClientId(authClientDetails.getClientId());
clientDetails.setClientSecret(authClientDetails.getClientSecret());
clientDetails.setAccessTokenValiditySeconds(authClientDetails.getAccessTokenValidity());
clientDetails.setRefreshTokenValiditySeconds(authClientDetails.getRefreshTokenValidity());
clientDetails.setScope(Collections.singletonList("all"));
// 这里设置为"true"表示所有的scope都会自动审批通过。
clientDetails.setAutoApproveScopes(Collections.singletonList("true"));
if (StringUtils.isNotBlank(authClientDetails.getAuthorizedGrantTypes())) {
clientDetails.setAuthorizedGrantTypes(Arrays.stream(StringUtils.split(
authClientDetails.getAuthorizedGrantTypes(), ",")).collect(Collectors.toSet()));
}
if (StringUtils.isNotBlank(authClientDetails.getWebServerRedirectUri())) {
clientDetails.setRegisteredRedirectUri(Arrays.stream(StringUtils.split(
authClientDetails.getWebServerRedirectUri(), ",")).collect(Collectors.toSet()));
}
return clientDetails;
}
}

View File

@@ -0,0 +1,71 @@
package com.orangeforms.uaaauth.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.code.RandomValueAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.store.redis.JdkSerializationStrategy;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStoreSerializationStrategy;
import org.springframework.stereotype.Service;
/**
* 在OAuth2授权码验证模式下请求的授权码都会存储到redis中以实现UAA服务的分布式部署。
* 同时也提升了验证过程的执行效率。
*
* @author Jerry
* @date 2020-08-08
*/
@Service
public class RedisAuthorizationCodeServices extends RandomValueAuthorizationCodeServices {
@Autowired
private RedisConnectionFactory redisConnectionFactory;
private final RedisTokenStoreSerializationStrategy serializationStrategy = new JdkSerializationStrategy();
private static final int EXPIRED_SECONDS = 10 * 60;
private RedisConnection getConnection() {
return redisConnectionFactory.getConnection();
}
/**
* 将授权码存储到redis中。
*/
@Override
protected void store(String code, OAuth2Authentication authentication) {
RedisConnection connection = getConnection();
try {
byte[] key = serializationStrategy.serialize(redisKey(code));
connection.set(key, serializationStrategy.serialize(authentication));
connection.expire(key, EXPIRED_SECONDS);
} finally {
connection.close();
}
}
/**
* 将授权码从redis中删除。
*/
@Override
protected OAuth2Authentication remove(final String code) {
OAuth2Authentication token = null;
RedisConnection connection = getConnection();
try {
byte[] key = serializationStrategy.serialize(redisKey(code));
byte[] value = connection.get(key);
if (value != null) {
connection.del(key);
token = serializationStrategy.deserialize(value, OAuth2Authentication.class);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
connection.close();
}
return token;
}
private String redisKey(String code) {
return "oauth:code:" + code;
}
}

View File

@@ -0,0 +1,56 @@
package com.orangeforms.uaaauth.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.orangeforms.uaaauth.dao.SysUaaUserMapper;
import com.orangeforms.uaaauth.model.SysUaaUser;
import com.orangeforms.common.core.base.service.BaseService;
import com.orangeforms.common.core.base.dao.BaseDaoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 用户管理数据操作服务类。
*
* @author Jerry
* @date 2020-08-08
*/
@Service
public class SysUaaUserService extends BaseService<SysUaaUser, Long> {
@Autowired
private SysUaaUserMapper sysUserMapper;
@Autowired
private PasswordEncoder passwordEncoder;
/**
* 返回当前Service的主表Mapper对象。
*
* @return 主表Mapper对象。
*/
@Override
protected BaseDaoMapper<SysUaaUser> mapper() {
return sysUserMapper;
}
public SysUaaUser getByUsername(String username) {
SysUaaUser filter = new SysUaaUser();
filter.setUsername(username);
return sysUserMapper.selectOne(new QueryWrapper<>(filter));
}
/**
* 修改用户密码。
* @param userId 用户主键Id。
* @param newPass 新密码。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
public boolean changePassword(Long userId, String newPass) {
SysUaaUser updatedUser = new SysUaaUser();
updatedUser.setUserId(userId);
updatedUser.setPassword(passwordEncoder.encode(newPass));
return sysUserMapper.updateById(updatedUser) == 1;
}
}

View File

@@ -0,0 +1,47 @@
package com.orangeforms.uaaauth.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.orangeforms.uaaauth.dao.SysUaaUserMapper;
import com.orangeforms.uaaauth.model.SysUaaUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Collections;
/**
* UAA授权用户数据操作服务类。该类必须为UserDetailsService接口的实现类。
* loadUserByUsername方法被Oauth2框架调用获取授权用户数据。
*
* @author Jerry
* @date 2020-08-08
*/
@Slf4j
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private SysUaaUserMapper mapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
SysUaaUser filter = new SysUaaUser();
filter.setUsername(username);
SysUaaUser sysUaaUser = mapper.selectOne(new QueryWrapper<>(filter));
if (sysUaaUser == null) {
throw new UsernameNotFoundException("用户名不存在![" + username + "]");
}
return new User(
sysUaaUser.getUsername(),
sysUaaUser.getPassword(),
true,
true,
true,
!sysUaaUser.getLocked(),
Collections.emptyList());
}
}

View File

@@ -0,0 +1,88 @@
package com.orangeforms.uaaauth.util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Enumeration;
/**
* 认证授权相关工具类。该类直接取自zlt感谢作者。
*
* @author Jerry
* @date 2020-08-08
*/
@Slf4j
public final class AuthUtils {
private AuthUtils() {
throw new IllegalStateException("Utility class");
}
private static final String BASIC = "Basic ";
private static final String CLIENT_STR_SEPERATOR = ":";
private static final int CLIENT_STR_ARRAY_LENGTH = 2;
/**
* 获取requet(head/param)中的token
*/
public static String extractToken(HttpServletRequest request) {
String token = extractHeaderToken(request);
if (token == null) {
token = request.getParameter(OAuth2AccessToken.ACCESS_TOKEN);
if (token == null) {
log.debug("Token not found in request parameters. Not an OAuth2 request.");
}
}
return token;
}
/**
* 解析head中的token
*/
private static String extractHeaderToken(HttpServletRequest request) {
Enumeration<String> headers = request.getHeaders("Authorization");
while (headers.hasMoreElements()) {
String value = headers.nextElement();
if ((value.startsWith(OAuth2AccessToken.BEARER_TYPE))) {
String authHeaderValue = value.substring(OAuth2AccessToken.BEARER_TYPE.length()).trim();
int commaIndex = authHeaderValue.indexOf(',');
if (commaIndex > 0) {
authHeaderValue = authHeaderValue.substring(0, commaIndex);
}
return authHeaderValue;
}
}
return null;
}
/**
* *从header 请求中的clientId:clientSecret
*/
public static String[] extractClient(HttpServletRequest request) {
String header = request.getHeader("Authorization");
if (header == null || !header.startsWith(BASIC)) {
throw new UnapprovedClientAuthenticationException("请求头中client信息为空");
}
return extractHeaderClient(header);
}
/**
* 从header 请求中的clientId:clientSecret
*
* @param header header中的参数
*/
public static String[] extractHeaderClient(String header) {
byte[] base64Client = header.substring(BASIC.length()).getBytes(StandardCharsets.UTF_8);
byte[] decoded = Base64.getDecoder().decode(base64Client);
String clientStr = new String(decoded, StandardCharsets.UTF_8);
String[] clientArr = clientStr.split(CLIENT_STR_SEPERATOR);
if (CLIENT_STR_ARRAY_LENGTH != clientArr.length) {
throw new RuntimeException("Invalid basic authentication token");
}
return clientArr;
}
}

View File

@@ -0,0 +1,17 @@
spring:
application:
name: uaa-auth
profiles:
active: dev
cloud:
nacos:
config:
server-addr: localhost:8848
file-extension: yaml
# 共享配置文件,排序越高后,优先级越高。
shared-configs:
- data-id: application-dev.yaml
group: DEFAULT_GROUP
refresh: true
main:
allow-bean-definition-overriding: true

View File

@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 本项目全部使用log4j2性能上有很大提升 -->
<!--monitorInterval="60" 自动检测配置文件更改时间 单位为秒 最小值为5 -->
<!--Configuration后面的status这个用于设置log4j2自身内部的信息输出可以不设置当设置成trace时你会看到log4j2内部各种详细输出。 -->
<configuration monitorInterval="20" status="OFF">
<!--日志变量 -->
<properties>
<!-- 日志主目录 ,需要保存到文件时请自己配置-->
<property name="LOG_HOME">./zzlogs/uaa-auth</property>
<!-- 日志备份目录 -->
<property name="BACKUP_HOME">./zzlogs/uaa-auth/backup</property>
<!-- 日志输出级别 -->
<property name="OUTPUT_LOG_LEVEL">info</property>
<!-- 日志输出格式 -->
<property name="LOG_PATTERN">
<!-- 输出格式%d{HH:mm:ss}时间24小时制 -->
<!-- %-5p日志级别 5位左对齐 [%t]线程名 [%c]类名 -->
<!--%l输出日志事件的发生位置相当于%c.%M(%F:%L)的组合包括类全名、方法、文件名以及在代码中的行数。例如test.TestLog4j.main(TestLog4j.java:10)。 -->
<!-- 另一种输出风格<PatternLayout pattern="级别%-5p [%d{YYYY-MM-dd HH:mm:ss}] [%t] 位置[%l] - 信息:%msg%n" /> -->
<!-- [%-5p][%d{yy-MM-dd HH:mm:ss}][%t]==>%m==>%c==>%L%n -->
[%-5p] [%d{YYYY-MM-dd HH:mm:ss}] [%t] ==> %msg%n
</property>
<property name="LOG_PATTERN_EX">
<!-- 下面注释中 %traceid 为SkyWalking 中的traceid -->
[%-5p] [%d{YYYY-MM-dd HH:mm:ss}] [%t] ==> [%traceId] %msg%n
</property>
<!-- 日志保留天数 -->
<property name="EVERY_FILE_COUNT">31</property>
<!-- 日志切割的最小单位 -->
<property name="EVERY_FILE_SIZE">20M</property>
</properties>
<appenders>
<!--Kafka输出 -->
<Kafka name="kafka_log" topic="zz-log-topic" syncSend="false" ignoreExceptions="false">
<PatternLayout pattern="${LOG_PATTERN_EX}"/>
<Property name="bootstrap.servers">localhost:9092</Property>
<Property name="max.block.ms">10000</Property>
</Kafka>
<!--控制台输出 -->
<console name="console" target="SYSTEM_OUT">
<PatternLayout pattern="${LOG_PATTERN}"/>
</console>
<!--每次大小超过size则这size大小的日志会自动进行压缩作为存档 -->
<rollingFile name="file_log" fileName="${LOG_HOME}/uaa-auth.log"
filePattern="${LOG_HOME}/uaa-auth-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout charset="UTF-8" pattern="${LOG_PATTERN_EX}"/>
<!-- 日志切割的最小单位 -->
<SizeBasedTriggeringPolicy size="${EVERY_FILE_SIZE}"/>
<!-- 默认的日志文件数量 -->
<DefaultRolloverStrategy max="${EVERY_FILE_COUNT}"/>
</rollingFile>
</appenders>
<!-- 然后定义logger只有定义了logger并引入的appenderappender才会生效 -->
<!-- 这里我们把输出到控制台appender的日志级别设置为DEBUG便于调试。但是输出文件我们缺省为INFO两者均可随时修改。-->
<Loggers>
<Root level="${OUTPUT_LOG_LEVEL}">
<AppenderRef ref="console"/>
</Root>
<!-- AsyncLogger 是基于Disruptor的全量异步队列性能极高队列默认大小4096。-->
<!-- 队列默认值可通过JVM参数设置参考博客https://www.jianshu.com/p/82469047acbf -->
<AsyncLogger name="com.orangeforms" additivity="false" level="info">
<AppenderRef ref="console"/>
<AppenderRef ref="kafka_log"/>
<AppenderRef ref="file_log"/>
</AsyncLogger>
<!-- 这里将dao的日志级别设置为DEBUG是为了SQL语句的输出 -->
<AsyncLogger name="com.orangeforms.uaaauth.dao" additivity="false" level="debug">
<AppenderRef ref="console"/>
<AppenderRef ref="kafka_log"/>
<AppenderRef ref="file_log"/>
</AsyncLogger>
</Loggers>
</configuration>

View File

@@ -0,0 +1,173 @@
header{
width: 100%;
height: 50px;
background: #1e1b29;
border-bottom: solid 4px red;
}
.member_wrap{
}
.header_item{
overflow: hidden;
}
.header_item{
width: 980px;
margin: 0 auto;
}
.menu_head{
width: 100px;
height: 100px;
border-radius: 100px;
border: solid 3px #fff;
overflow: hidden;
}
.menu_head img{
width: 100%;
height: 100%;
}
.menu_info{
width:840px;
margin-left: 20px;
}
.info_name{
font-size: 18px;
line-height: 40px;
font-weight: bold;
color: #fff;
}
.info_name_box{
margin-top: 10px;
}
.level{
font-size: 14px;
color: #f60;
font-weight: bold;
}
.info_desc{
margin-top: 10px;
font-size: 14px;
color: #FFF;
}
.banner_menu{
width: 980px;
height: 50px;
margin: 20px auto;
background: #fff;
}
.nav_box{
margin-top: 50px;
}
.nav_box ul {
overflow: hidden;
}
.nav_box ul li{
display: block;
padding: 0 20px;
}
.nav_box ul li a{
color: #fff;
font-size: 16px;
}
.nav_box ul li a:hover{
color: red;
}
.login_wrap{
background: url(/images/logo_bg.jpg) no-repeat center;
/*background-size: 100%;*/
}
.logo{
width: 500px;
height: 150px;
margin: 0px auto;
background: url(/images/logowz.png) no-repeat center;
}
.login_box{
width: 360px;
background: #FFFFFF;
margin: 0px auto;
}
.login_title{
font-size: 25px;
text-align: center;
color: #FF7F50;
padding: 15px 0;
width: 300px;
margin: 0 auto;
border-bottom: solid 1px #CCCCCC;
}
.form_text_ipt{
width: 300px;
height: 40px;
border: solid 1px #CCCCCC;
margin: 20px auto 0 auto;
background: #FFFFFF;
}
.form_check_ipt{
width: 300px;
margin: 10px auto;
overflow: hidden;
}
.form_text_ipt input{
width: 290px;
height: 30px;
margin: 5px;
border: none;
font-family: "微软雅黑";
font-size: 15px;
color: #666;
}
.check_left label{
cursor: pointer;
}
.check_left label input{
position: relative;
top: 2px;
}
.form_btn{
width: 300px;
height: 40px;
margin: 10px auto;
}
.form_btn button{
width: 100%;
height: 100%;
border: none;
color: #FFFFFF;
font-size: 14px;
background: #FF7F50;
cursor: pointer;
}
.form_reg_btn{
width: 300px;
margin: 0 auto;
font-size: 14px;
color: #666;
}
.other_login{
overflow: hidden;
width: 300px;
height: 80px;
line-height: 80px;
margin: 0px auto;
}
.other_left{
font-size: 14px;
color: #999;
}
.other_right a{
margin:5px;
color:#636363;
}
.other_right a:hover{
color:#AEEEEE;
}

View File

@@ -0,0 +1,39 @@
/*reset*/
*{padding: 0;margin: 0;}
html, body, body div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, figure, footer, header, menu, nav, section, time, mark, audio, video, details, summary {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font-weight: normal;
vertical-align: baseline;
background: transparent;
}
article, aside, figure, footer, header, nav, section, details, summary {display: block;}
html, body { height: 100%; color: #333; font-size: 12px; font-family: "微软雅黑",MicrosoftYaHei;}
a { text-decoration: none; color: #3cf; -webkit-tap-highlight-color: transparent;}
li{list-style: none;}
table{border-collapse: collapse;}
input {outline: medium none;font-family: "微软雅黑",MicrosoftYaHei;font-size: 14px;}
button{font-family:"微软雅黑",MicrosoftYaHei;}
em {font-style: normal;}
.wrap{max-width: 100%;min-height: 100%;overflow: hidden;margin: 0 auto;background: #ccc;}
.left{float: left;}
.right{float: right;}
.clear{clear:both;}
.red{color: #f60;}
.ececk_warning{
font-size: 13px;
color: red;
width: 300px;
margin: 0 auto;
display: none;
}
._warning{
font-size: 13px;
color: red;
width: 300px;
margin: 0 auto;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@@ -0,0 +1,50 @@
$(function(){
$('.form_text_ipt input').focus(function(){
$(this).parent().css({
'box-shadow':'0 0 3px #bbb',
});
});
$('.form_text_ipt input').blur(function(){
$(this).parent().css({
'box-shadow':'none',
});
});
$('.form_text_ipt input').bind('input propertychange',function(){
if($(this).val()==""){
$(this).css({
'color':'red',
});
$(this).parent().css({
'border':'solid 1px red',
});
$(this).parent().next().show();
}else{
$(this).css({
'color':'#ccc',
});
$(this).parent().css({
'border':'solid 1px #ccc',
});
$(this).parent().next().hide();
}
});
let query = location.search;
if (query === '?error') {
$('#loginError').show();
}
});
function checkForm(){
var inputPwd = document.getElementById('input_pwd');
var rsaPwd = document.getElementById('rsa_pwd');
// 加密
let encrypt = new JSEncrypt();
var publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpC4QMnbTrQOFriJJCCFFWhlruBJThAEBfRk7pRx1jsAhyNVL3CqJb0tRvpnbCnJhrRAEPdgFHXv5A0RrvFp+5Cw7QoFH6O9rKB8+0H7+aVQeKITMUHf/XMXioymw6Iq4QfWd8RhdtM1KM6eGTy8aU7SO2s69Mc1LXefg/x3yw6wIDAQAB';
encrypt.setPublicKey(publicKey);
rsaPwd.value= encodeURIComponent(encrypt.encrypt(inputPwd.value));
//进行下一步
return true;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>登录界面</title>
<link rel="stylesheet" href="/css/reset.css"/>
<link rel="stylesheet" href="/css/common.css"/>
</head>
<body>
<div class="wrap login_wrap">
<div class="content">
<div class="logo"></div>
<div class="login_box">
<div class="login_form">
<div class="login_title">
登录
</div>
<form action="/uaa/login" method="post" onsubmit='return checkForm()'>
<div class="form_text_ipt">
<input name="username" type="text" placeholder="用户名" value="admin">
</div>
<div class="ececk_warning"><span>用户名不能为空</span></div>
<div class="_warning"><span></span></div>
<div class="form_text_ipt">
<input type="password" id='input_pwd' placeholder="密码" value="123456">
<input type='hidden' name='password' id='rsa_pwd' value=''/>
</div>
<div class="ececk_warning"><span>密码不能为空</span></div>
<div class="form_btn">
<button type="submit">登录</button>
</div>
<div id="loginError" class="ececk_warning" style="text-align: center;"><span>用户名或密码错误</span></div>
<div class="form_reg_btn">
<!--span>还没有帐号?</span><a href="/register">马上注册</a-->
&nbsp;
</div>
</form>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="/js/jquery.min.js"></script>
<script type="text/javascript" src="/js/jsencrypt.min.js"></script>
<script type="text/javascript" src="/js/common.js"></script>
</body>
</html>

View File

@@ -0,0 +1,246 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Spring" name="Spring">
<configuration />
</facet>
<facet type="web" name="Web">
<configuration>
<webroots />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/target/generated-sources/annotations" isTestSource="false" generated="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="common-core" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.11.4" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.11.4" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.45" level="project" />
<orderEntry type="library" name="Maven: org.glassfish:jakarta.el:3.0.3" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:9.0.45" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:guava:29.0-jre" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:failureaccess:1.0.1" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava" level="project" />
<orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:3.0.2" level="project" />
<orderEntry type="library" name="Maven: org.checkerframework:checker-qual:2.11.1" level="project" />
<orderEntry type="library" name="Maven: com.google.errorprone:error_prone_annotations:2.3.4" level="project" />
<orderEntry type="library" name="Maven: com.google.j2objc:j2objc-annotations:1.3" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.10" level="project" />
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.14" level="project" />
<orderEntry type="library" name="Maven: commons-io:commons-io:2.6" level="project" />
<orderEntry type="library" name="Maven: commons-fileupload:commons-fileupload:1.3.3" level="project" />
<orderEntry type="library" name="Maven: joda-time:joda-time:2.9.9" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-collections4:4.4" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-csv:1.8" level="project" />
<orderEntry type="library" name="Maven: cn.hutool:hutool-all:5.6.4" level="project" />
<orderEntry type="library" name="Maven: io.jsonwebtoken:jjwt:0.9.1" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.11.4" level="project" />
<orderEntry type="library" name="Maven: com.alibaba:fastjson:1.2.76" level="project" />
<orderEntry type="library" name="Maven: com.github.ben-manes.caffeine:caffeine:2.8.8" level="project" />
<orderEntry type="library" name="Maven: cn.jimmyshi:bean-query:1.1.5" level="project" />
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-all:1.3" level="project" />
<orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.9.3" level="project" />
<orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.2" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.30" level="project" />
<orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml:3.17" level="project" />
<orderEntry type="library" name="Maven: org.apache.poi:poi:3.17" level="project" />
<orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml-schemas:3.17" level="project" />
<orderEntry type="library" name="Maven: org.apache.xmlbeans:xmlbeans:2.6.0" level="project" />
<orderEntry type="library" name="Maven: stax:stax-api:1.0.1" level="project" />
<orderEntry type="library" name="Maven: com.github.virtuald:curvesapi:1.04" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: mysql:mysql-connector-java:8.0.23" level="project" />
<orderEntry type="library" name="Maven: com.alibaba:druid-spring-boot-starter:1.2.6" level="project" />
<orderEntry type="library" name="Maven: com.alibaba:druid:1.2.6" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-boot-starter:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-extension:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-core:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-annotation:3.4.2" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.zaxxer:HikariCP:3.4.5" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper-spring-boot-starter:1.3.0" level="project" />
<orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.3" level="project" />
<orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-autoconfigure:2.1.3" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis:3.5.5" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:2.0.5" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper-spring-boot-autoconfigure:1.3.0" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper:5.2.0" level="project" />
<orderEntry type="library" name="Maven: com.github.jsqlparser:jsqlparser:3.2" level="project" />
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-oauth2:2.2.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-security:2.2.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-security:2.2.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-security:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.1.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.11.4" level="project" />
<orderEntry type="library" name="Maven: com.sun.xml.bind:jaxb-core:2.3.0.1" level="project" />
<orderEntry type="library" name="Maven: com.sun.xml.bind:jaxb-impl:2.3.0.1" level="project" />
<orderEntry type="library" name="Maven: javax.xml.bind:jaxb-api:2.3.1" level="project" />
<orderEntry type="library" name="Maven: javax.activation:javax.activation-api:1.2.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-jwt:1.0.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.bouncycastle:bcpkix-jdk15on:1.59" level="project" />
<orderEntry type="library" name="Maven: org.bouncycastle:bcprov-jdk15on:1.59" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security.oauth:spring-security-oauth2:2.3.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-webmvc:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:5.3.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-config:5.3.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-web:5.3.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.codehaus.jackson:jackson-mapper-asl:1.9.13" level="project" />
<orderEntry type="library" name="Maven: org.codehaus.jackson:jackson-core-asl:1.9.13" level="project" />
<orderEntry type="library" name="Maven: org.springframework.session:spring-session-data-redis:2.3.3.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.data:spring-data-redis:2.3.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.data:spring-data-keyvalue:2.3.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.data:spring-data-commons:2.3.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-tx:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-oxm:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.session:spring-session-core:2.3.3.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-data-redis:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: jakarta.annotation:jakarta.annotation-api:1.3.5" level="project" />
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.26" level="project" />
<orderEntry type="library" name="Maven: io.lettuce:lettuce-core:5.3.7.RELEASE" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-common:4.1.63.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-handler:4.1.63.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-resolver:4.1.63.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-buffer:4.1.63.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-codec:4.1.63.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-transport:4.1.63.Final" level="project" />
<orderEntry type="library" name="Maven: io.projectreactor:reactor-core:3.3.16.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-freemarker:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.freemarker:freemarker:2.3.31" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context-support:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: javax.servlet:javax.servlet-api:4.0.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-log4j2:2.6.1" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.30" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-core:2.15.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-jul:2.15.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-slf4j-impl:2.15.0" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.30" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.15.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-aop:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.aspectj:aspectjweaver:1.9.6" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-cache:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-configuration-processor:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-actuator:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-actuator-autoconfigure:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-actuator:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.11.4" level="project" />
<orderEntry type="library" name="Maven: io.micrometer:micrometer-core:1.5.13" level="project" />
<orderEntry type="library" name="Maven: org.hdrhistogram:HdrHistogram:2.1.12" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.latencyutils:LatencyUtils:2.0.3" level="project" />
<orderEntry type="library" name="Maven: de.codecentric:spring-boot-admin-starter-client:2.3.1" level="project" />
<orderEntry type="library" name="Maven: de.codecentric:spring-boot-admin-client:2.3.1" level="project" />
<orderEntry type="library" name="Maven: com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-config:2.2.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.alibaba.spring:spring-context-support:1.0.10" level="project" />
<orderEntry type="library" name="Maven: com.alibaba.nacos:nacos-client:1.4.1" level="project" />
<orderEntry type="library" name="Maven: com.alibaba.nacos:nacos-common:1.4.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpasyncclient:4.1.4" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore-nio:4.4.14" level="project" />
<orderEntry type="library" name="Maven: com.alibaba.nacos:nacos-api:1.4.1" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.11.4" level="project" />
<orderEntry type="library" name="Maven: io.prometheus:simpleclient:0.5.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-commons:2.2.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-crypto:5.3.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-context:2.2.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-openfeign:2.2.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter:2.2.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-rsa:1.0.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-openfeign-core:2.2.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: io.github.openfeign.form:feign-form-spring:3.8.0" level="project" />
<orderEntry type="library" name="Maven: io.github.openfeign.form:feign-form:3.8.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-web:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: io.github.openfeign:feign-core:10.10.1" level="project" />
<orderEntry type="library" name="Maven: io.github.openfeign:feign-slf4j:10.10.1" level="project" />
<orderEntry type="library" name="Maven: io.github.openfeign:feign-hystrix:10.10.1" level="project" />
<orderEntry type="library" name="Maven: com.netflix.archaius:archaius-core:0.7.6" level="project" />
<orderEntry type="library" name="Maven: io.github.openfeign:feign-httpclient:10.10.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.5.13" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.4.14" level="project" />
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-netflix-hystrix:2.2.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-netflix-hystrix:2.2.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-netflix-ribbon:2.2.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-netflix-archaius:2.2.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-netflix-archaius:2.2.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: commons-configuration:commons-configuration:1.8" level="project" />
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.6" level="project" />
<orderEntry type="library" name="Maven: com.netflix.hystrix:hystrix-core:1.5.18" level="project" />
<orderEntry type="library" name="Maven: io.reactivex:rxjava:1.3.8" level="project" />
<orderEntry type="library" name="Maven: com.netflix.hystrix:hystrix-serialization:1.5.18" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: com.fasterxml.jackson.module:jackson-module-afterburner:2.11.4" level="project" />
<orderEntry type="library" name="Maven: com.netflix.hystrix:hystrix-metrics-event-stream:1.5.18" level="project" />
<orderEntry type="library" name="Maven: com.netflix.hystrix:hystrix-javanica:1.5.18" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.ow2.asm:asm:5.0.4" level="project" />
<orderEntry type="library" name="Maven: io.reactivex:rxjava-reactive-streams:1.2.1" level="project" />
<orderEntry type="library" name="Maven: org.reactivestreams:reactive-streams:1.0.3" level="project" />
<orderEntry type="library" name="Maven: org.hibernate.validator:hibernate-validator:6.2.0.Final" level="project" />
<orderEntry type="library" name="Maven: jakarta.validation:jakarta.validation-api:2.0.2" level="project" />
<orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.4.1.Final" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml:classmate:1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.mapstruct:mapstruct:1.4.2.Final" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.mapstruct:mapstruct-processor:1.4.2.Final" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.projectlombok:lombok:1.18.20" level="project" />
<orderEntry type="library" name="Maven: org.apache.curator:curator-recipes:4.3.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.curator:curator-framework:4.0.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.curator:curator-client:4.0.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.zookeeper:zookeeper:3.5.3-beta" level="project" />
<orderEntry type="library" name="Maven: commons-cli:commons-cli:1.4" level="project" />
<orderEntry type="library" name="Maven: org.apache.kafka:kafka-clients:2.4.0" level="project" />
<orderEntry type="library" name="Maven: com.github.luben:zstd-jni:1.4.3-1" level="project" />
<orderEntry type="library" name="Maven: org.lz4:lz4-java:1.6.0" level="project" />
<orderEntry type="library" name="Maven: org.xerial.snappy:snappy-java:1.1.7.3" level="project" />
<orderEntry type="library" name="Maven: org.scala-lang:scala-library:2.12.10" level="project" />
<orderEntry type="library" name="Maven: com.lmax:disruptor:3.4.3" level="project" />
<orderEntry type="library" name="Maven: org.apache.skywalking:apm-toolkit-log4j-2.x:7.0.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.plugin:spring-plugin-core:2.0.0.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.plugin:spring-plugin-metadata:2.0.0.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:2.3.10.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:2.3.10.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:2.3.10.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.4.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:1.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: jakarta.xml.bind:jakarta.xml.bind-api:2.3.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: jakarta.activation:jakarta.activation-api:1.2.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:3.16.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest:2.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter:5.6.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-api:5.6.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.opentest4j:opentest4j:1.2.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-commons:1.6.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-params:5.6.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-engine:5.6.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.vintage:junit-vintage-engine:5.6.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.apiguardian:apiguardian-api:1.1.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-engine:1.6.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.13.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:3.3.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy:1.10.22" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy-agent:1.10.22" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:2.6" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-junit-jupiter:3.3.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.5.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:5.2.14.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.xmlunit:xmlunit-core:2.7.0" level="project" />
</component>
</module>