mirror of
https://gitee.com/orangeform/orange-admin.git
synced 2026-01-18 19:16:37 +08:00
commit:微服务uaa版本
This commit is contained in:
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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> {
|
||||
}
|
||||
@@ -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> {
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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并引入的appender,appender才会生效 -->
|
||||
<!-- 这里我们把输出到控制台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>
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 |
@@ -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
@@ -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-->
|
||||
|
||||
</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>
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user