@@ -1,7 +1,7 @@ | |||
Server端 项目 | |||
第一步:登录授权获取code: | |||
http://127.0.0.1:8090/oauth2/authorize? | |||
client_id=tuoheng-dsp | |||
client_id=tuoheng-dsp-web | |||
&response_type=code | |||
&scope=openid+profile | |||
&redirect_uri=http://192.168.11.11:8086/home |
@@ -11,6 +11,7 @@ | |||
</parent> | |||
<modules> | |||
<module>tuoheng_oidc_server</module> | |||
<module>tuoheng_oidc_admin</module> | |||
</modules> | |||
<groupId>com.tuoheng</groupId> | |||
<artifactId>tuoheng_oidc</artifactId> |
@@ -0,0 +1,225 @@ | |||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<modelVersion>4.0.0</modelVersion> | |||
<parent> | |||
<groupId>com.tuoheng</groupId> | |||
<artifactId>tuoheng_oidc</artifactId> | |||
<version>1.0.0</version> | |||
</parent> | |||
<groupId>com.tuoheng</groupId> | |||
<artifactId>tuoheng_oidc_admin</artifactId> | |||
<version>1.0.0</version> | |||
<name>tuoheng_oidc_admin</name> | |||
<description>tuoheng_oidc_admin</description> | |||
<properties> | |||
<java.version>1.8</java.version> | |||
</properties> | |||
<dependencies> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-web</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-test</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
<!-- 数据库 --> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-jdbc</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>mysql</groupId> | |||
<artifactId>mysql-connector-java</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-data-redis</artifactId> | |||
</dependency> | |||
<!--MyBatis整合SpringBoot框架的起步依赖--> | |||
<dependency> | |||
<groupId>org.mybatis.spring.boot</groupId> | |||
<artifactId>mybatis-spring-boot-starter</artifactId> | |||
<version>2.2.1</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.projectlombok</groupId> | |||
<artifactId>lombok</artifactId> | |||
<version>1.18.22</version> | |||
</dependency> | |||
<!-- 数据连接池 --> | |||
<dependency> | |||
<groupId>com.alibaba</groupId> | |||
<artifactId>druid-spring-boot-starter</artifactId> | |||
<version>1.2.9</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-validation</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-thymeleaf</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>io.jsonwebtoken</groupId> | |||
<artifactId>jjwt</artifactId> | |||
<version>0.9.0</version> | |||
</dependency> | |||
<!-- JSON 解析器和生成器 --> | |||
<dependency> | |||
<groupId>com.alibaba</groupId> | |||
<artifactId>fastjson</artifactId> | |||
<version>1.2.76</version> | |||
</dependency> | |||
<!-- SpringCloud依赖 --> | |||
<dependency> | |||
<groupId>org.springframework.cloud</groupId> | |||
<artifactId>spring-cloud-dependencies</artifactId> | |||
<version>2021.0.3</version> | |||
<type>pom</type> | |||
<scope>import</scope> | |||
</dependency> | |||
<!-- Consul注册中心起始依赖 --> | |||
<dependency> | |||
<groupId>org.springframework.cloud</groupId> | |||
<artifactId>spring-cloud-starter-consul-discovery</artifactId> | |||
<version>3.1.1</version> | |||
</dependency> | |||
</dependencies> | |||
<!-- 构建环境变量 --> | |||
<profiles> | |||
<!-- 本地开发环境 --> | |||
<profile> | |||
<id>local</id> | |||
<properties> | |||
<package.environment>local</package.environment> | |||
</properties> | |||
<activation> | |||
<activeByDefault>true</activeByDefault> | |||
</activation> | |||
</profile> | |||
<!-- 开发环境 --> | |||
<profile> | |||
<id>dev</id> | |||
<properties> | |||
<package.environment>dev</package.environment> | |||
</properties> | |||
</profile> | |||
<!-- 测试环境 --> | |||
<profile> | |||
<id>test</id> | |||
<properties> | |||
<package.environment>test</package.environment> | |||
</properties> | |||
</profile> | |||
<!-- 生产环境 --> | |||
<profile> | |||
<id>prod</id> | |||
<properties> | |||
<package.environment>prod</package.environment> | |||
</properties> | |||
</profile> | |||
</profiles> | |||
<!-- 环境变量构建 --> | |||
<build> | |||
<finalName>tuoheng_oidc_admin</finalName> | |||
<resources> | |||
<resource> | |||
<directory>src/main/resources</directory> | |||
<filtering>true</filtering> | |||
</resource> | |||
<resource> | |||
<directory>src/main/java</directory> | |||
<includes> | |||
<include>**/*.*</include> | |||
</includes> | |||
<excludes> | |||
<exclude>**/*.java</exclude> | |||
</excludes> | |||
</resource> | |||
<resource> | |||
<directory>src/main/resources</directory> | |||
<filtering>true</filtering> | |||
<targetPath>WEB-INF/classes</targetPath> | |||
<includes> | |||
<include>application-${package.environment}.yml</include> | |||
</includes> | |||
</resource> | |||
</resources> | |||
<pluginManagement> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-resources-plugin</artifactId> | |||
<configuration> | |||
<delimiters>@</delimiters> | |||
<useDefaultDelimiters>false</useDefaultDelimiters> | |||
</configuration> | |||
</plugin> | |||
<plugin> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-maven-plugin</artifactId> | |||
<version>2.1.11.RELEASE</version> | |||
<configuration> | |||
<finalName>${project.build.finalName}</finalName> | |||
</configuration> | |||
<executions> | |||
<execution> | |||
<goals> | |||
<goal>repackage</goal> | |||
</goals> | |||
</execution> | |||
</executions> | |||
</plugin> | |||
</plugins> | |||
</pluginManagement> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-resources-plugin</artifactId> | |||
<version>3.1.0</version> | |||
</plugin> | |||
<plugin> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-maven-plugin</artifactId> | |||
<executions> | |||
<execution> | |||
<goals> | |||
<goal>repackage</goal> | |||
</goals> | |||
</execution> | |||
</executions> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</project> |
@@ -0,0 +1,14 @@ | |||
package com.tuoheng; | |||
import org.springframework.boot.SpringApplication; | |||
import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
@SpringBootApplication | |||
public class TuohengOidcAdminApplication { | |||
public static void main(String[] args) { | |||
SpringApplication.run(TuohengOidcAdminApplication.class, args); | |||
System.out.println("TuoHeng-Oidc-Admin 启动成功~"); | |||
} | |||
} |
@@ -0,0 +1,50 @@ | |||
package com.tuoheng.config; | |||
import com.alibaba.fastjson.JSON; | |||
import com.alibaba.fastjson.JSONObject; | |||
import com.tuoheng.mapper.ClientUserMapper; | |||
import com.tuoheng.model.dto.LoginUser; | |||
import com.tuoheng.model.po.UserPo; | |||
import com.tuoheng.service.CurrentUser; | |||
import com.tuoheng.until.EncryptUtil; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.core.MethodParameter; | |||
import org.springframework.stereotype.Component; | |||
import org.springframework.web.bind.support.WebDataBinderFactory; | |||
import org.springframework.web.context.request.NativeWebRequest; | |||
import org.springframework.web.method.support.HandlerMethodArgumentResolver; | |||
import org.springframework.web.method.support.ModelAndViewContainer; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/27 11:34 | |||
*/ | |||
@Component | |||
public class LoginUserHandler implements HandlerMethodArgumentResolver { | |||
@Override | |||
public boolean supportsParameter(MethodParameter parameter) { | |||
return parameter.hasParameterAnnotation(CurrentUser.class) && | |||
parameter.getParameterType().isAssignableFrom(LoginUser.class); | |||
} | |||
@Override | |||
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container, | |||
NativeWebRequest request, WebDataBinderFactory factory) { | |||
// header中获取用户token | |||
String token = request.getHeader("th-token"); | |||
String oUserJson = request.getHeader("o-user-json"); | |||
String json = EncryptUtil.decodeUTF8StringBase64(oUserJson); | |||
JSONObject jsonObject = JSON.parseObject(json); | |||
String username = jsonObject.getString("username"); | |||
Long oidcUserId = jsonObject.getLong("oUserId"); | |||
// 这里可以自定义封装自己的用户信息 | |||
//UserPo userPo = clientUserMapper.getUserByUserName(username); | |||
LoginUser user = new LoginUser() | |||
.setUsername(username) | |||
.setUserId(oidcUserId) | |||
.setThToken(token); | |||
return user; | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
package com.tuoheng.config; | |||
import org.springframework.context.annotation.Configuration; | |||
import org.springframework.web.method.support.HandlerMethodArgumentResolver; | |||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | |||
import javax.annotation.Resource; | |||
import java.util.List; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/27 11:40 | |||
*/ | |||
@Configuration | |||
public class WebConfig implements WebMvcConfigurer { | |||
@Resource | |||
private LoginUserHandler loginUserHandler; | |||
@Override | |||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { | |||
argumentResolvers.add(loginUserHandler); | |||
} | |||
} |
@@ -0,0 +1,22 @@ | |||
package com.tuoheng.controller; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.web.bind.annotation.GetMapping; | |||
import org.springframework.web.bind.annotation.RestController; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/21 14:51 | |||
*/ | |||
@RestController | |||
@Slf4j | |||
public class DemoController { | |||
@GetMapping("getHealth") | |||
public String getHealth(){ | |||
log.info("tuoheng-oidc-admin is ok~"); | |||
return "tuoheng-oidc-admin is ok~"; | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
package com.tuoheng.controller; | |||
import com.tuoheng.model.dto.LoginUser; | |||
import com.tuoheng.model.param.CreateClientUserDto; | |||
import com.tuoheng.model.param.UpdateUserClientRoleDto; | |||
import com.tuoheng.model.param.UpdateUserPassDto; | |||
import com.tuoheng.service.ClientUserSevice; | |||
import com.tuoheng.service.CurrentUser; | |||
import com.tuoheng.until.JsonResult; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.validation.annotation.Validated; | |||
import org.springframework.web.bind.annotation.*; | |||
/** | |||
* @author chenjiandong | |||
* @description: 同步业务端 user 数据 | |||
* @date 2022/10/24 11:12 | |||
*/ | |||
@RestController | |||
@RequestMapping("/user") | |||
@Slf4j | |||
public class UserController { | |||
@Autowired | |||
private ClientUserSevice clientUserSevice; | |||
@GetMapping("/judge/create/{username}") | |||
public JsonResult judgeCreate(@PathVariable("username") String username){ | |||
return clientUserSevice.judgeCreate(username); | |||
} | |||
@PostMapping("/create") | |||
public JsonResult createClientUser(@RequestBody CreateClientUserDto createClientUserDto, | |||
@CurrentUser LoginUser loginUser){ | |||
return clientUserSevice.createClientUser(createClientUserDto, loginUser); | |||
} | |||
@PostMapping("/updatePass") | |||
public JsonResult updateUserPassword(@RequestBody @Validated UpdateUserPassDto updateUserPassDto, | |||
@CurrentUser LoginUser loginUser){ | |||
return clientUserSevice.updateUserPassword(updateUserPassDto, loginUser); | |||
} | |||
@PostMapping("/updateRole") | |||
public JsonResult updateUserClientRole(@RequestBody @Validated UpdateUserClientRoleDto updateUserClientRoleDto, | |||
@CurrentUser LoginUser loginUser){ | |||
return clientUserSevice.updateUserClientRole(updateUserClientRoleDto, loginUser); | |||
} | |||
} |
@@ -0,0 +1,18 @@ | |||
package com.tuoheng.mapper; | |||
import com.tuoheng.model.po.AuthoritiesPo; | |||
import org.apache.ibatis.annotations.Mapper; | |||
import java.util.List; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/9 10:39 | |||
*/ | |||
@Mapper | |||
public interface AuthoritiesMapper { | |||
int batchInsert(List<AuthoritiesPo> list); | |||
} |
@@ -0,0 +1,22 @@ | |||
package com.tuoheng.mapper; | |||
import com.tuoheng.model.po.UserPo; | |||
import org.apache.ibatis.annotations.Mapper; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/8 11:59 | |||
*/ | |||
@Mapper | |||
public interface ClientUserMapper { | |||
int insertClientUser(UserPo userPo); | |||
int judgeCreateByUserName(String username); | |||
UserPo getUserByUserName(String userName); | |||
int updatePass(UserPo userPo); | |||
} |
@@ -0,0 +1,21 @@ | |||
package com.tuoheng.mapper; | |||
import com.tuoheng.model.po.AuthoritiesPo; | |||
import com.tuoheng.model.po.ClientUserRolePo; | |||
import org.apache.ibatis.annotations.Mapper; | |||
import java.util.List; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/9 10:39 | |||
*/ | |||
@Mapper | |||
public interface ClientUserRoleMapper { | |||
int batchInsert(List<ClientUserRolePo> list); | |||
int updateUserClientRole(ClientUserRolePo clientUserRolePo); | |||
} |
@@ -0,0 +1,21 @@ | |||
package com.tuoheng.model.dto; | |||
import lombok.Data; | |||
import lombok.experimental.Accessors; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/27 11:34 | |||
*/ | |||
@Data | |||
@Accessors(chain = true) | |||
public class LoginUser { | |||
private String username; | |||
private Long userId; | |||
private String thToken; | |||
} |
@@ -0,0 +1,23 @@ | |||
package com.tuoheng.model.dto; | |||
import lombok.Data; | |||
import java.util.List; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/9 13:46 | |||
*/ | |||
@Data | |||
public class UserBaseInfoDto { | |||
private Integer userId; | |||
private String userName; | |||
private String password; | |||
private List<String> authorityList; | |||
} |
@@ -0,0 +1,17 @@ | |||
package com.tuoheng.model.param; | |||
import lombok.Data; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/26 9:30 | |||
*/ | |||
@Data | |||
public class ClientRoleDto { | |||
private String clientId; | |||
private Integer roleId; | |||
} |
@@ -0,0 +1,26 @@ | |||
package com.tuoheng.model.param; | |||
import lombok.Data; | |||
import javax.validation.constraints.NotEmpty; | |||
import javax.validation.constraints.NotNull; | |||
import java.util.List; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/8 11:30 | |||
*/ | |||
@Data | |||
public class CreateClientUserDto { | |||
@NotEmpty(message = "username can not be empty!") | |||
private String username; | |||
@NotEmpty(message = "password can not be empty!") | |||
private String password; | |||
@NotNull(message = "clientRoleDtoList can not be null!") | |||
private List<ClientRoleDto> clientRoleDtoList; | |||
} |
@@ -0,0 +1,21 @@ | |||
package com.tuoheng.model.param; | |||
import lombok.Data; | |||
import javax.validation.constraints.NotEmpty; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/8 11:30 | |||
*/ | |||
@Data | |||
public class GetUserInfoDto { | |||
@NotEmpty(message = "username can not be empty!") | |||
private String username; | |||
@NotEmpty(message = "token can not be empty!") | |||
private String token; | |||
} |
@@ -0,0 +1,24 @@ | |||
package com.tuoheng.model.param; | |||
import lombok.Data; | |||
import javax.validation.constraints.NotEmpty; | |||
import javax.validation.constraints.NotNull; | |||
import java.util.List; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/8 11:30 | |||
*/ | |||
@Data | |||
public class UpdateUserClientRoleDto { | |||
@NotEmpty(message = "username can not be empty!") | |||
private String username; | |||
@NotNull(message = "clientRoleDtoList can not be null!") | |||
private List<ClientRoleDto> clientRoleDtoList; | |||
} |
@@ -0,0 +1,23 @@ | |||
package com.tuoheng.model.param; | |||
import lombok.Data; | |||
import javax.validation.constraints.NotEmpty; | |||
import javax.validation.constraints.NotNull; | |||
import java.util.List; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/8 11:30 | |||
*/ | |||
@Data | |||
public class UpdateUserPassDto { | |||
@NotEmpty(message = "username can not be empty!") | |||
private String username; | |||
@NotEmpty(message = "password can not be empty!") | |||
private String password; | |||
} |
@@ -0,0 +1,23 @@ | |||
package com.tuoheng.model.po; | |||
import lombok.Data; | |||
import lombok.experimental.Accessors; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/9 10:20 | |||
*/ | |||
@Data | |||
@Accessors(chain = true) | |||
public class AuthoritiesPo extends BasePo { | |||
private Long id; | |||
private Long userId; | |||
private String username; | |||
private String authority; | |||
} |
@@ -0,0 +1,25 @@ | |||
package com.tuoheng.model.po; | |||
import lombok.Data; | |||
import lombok.experimental.Accessors; | |||
import java.sql.Date; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/26 9:34 | |||
*/ | |||
@Data | |||
@Accessors(chain = true) | |||
public class BasePo { | |||
private Date createTime; | |||
private Date updateTime; | |||
private Long createUser; | |||
private Long updateUser; | |||
} |
@@ -0,0 +1,25 @@ | |||
package com.tuoheng.model.po; | |||
import lombok.Data; | |||
import lombok.experimental.Accessors; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/26 9:36 | |||
*/ | |||
@Data | |||
@Accessors(chain = true) | |||
public class ClientUserRolePo extends BasePo { | |||
private Long id; | |||
private Long userId; | |||
private String clientId; | |||
private Integer roleId; | |||
private Integer status; | |||
} |
@@ -0,0 +1,23 @@ | |||
package com.tuoheng.model.po; | |||
import lombok.Data; | |||
import lombok.experimental.Accessors; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/8 12:07 | |||
*/ | |||
@Data | |||
@Accessors(chain = true) | |||
public class UserPo extends BasePo { | |||
private Long id; | |||
private String username; | |||
private String password; | |||
private Integer enabled; | |||
} |
@@ -0,0 +1,25 @@ | |||
package com.tuoheng.service; | |||
import com.tuoheng.model.dto.LoginUser; | |||
import com.tuoheng.model.param.CreateClientUserDto; | |||
import com.tuoheng.model.param.UpdateUserClientRoleDto; | |||
import com.tuoheng.model.param.UpdateUserPassDto; | |||
import com.tuoheng.until.JsonResult; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/8 11:35 | |||
*/ | |||
public interface ClientUserSevice { | |||
JsonResult judgeCreate(String username); | |||
JsonResult createClientUser(CreateClientUserDto createClientUserDto, LoginUser loginUser); | |||
JsonResult updateUserPassword(UpdateUserPassDto updateUserPassDto, LoginUser loginUser); | |||
JsonResult updateUserClientRole(UpdateUserClientRoleDto updateUserClientRoleDto, LoginUser loginUser); | |||
} |
@@ -0,0 +1,18 @@ | |||
package com.tuoheng.service; | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/27 11:33 | |||
*/ | |||
@Target(ElementType.PARAMETER) | |||
@Retention(RetentionPolicy.RUNTIME) | |||
public @interface CurrentUser { | |||
} |
@@ -0,0 +1,118 @@ | |||
package com.tuoheng.service.impl; | |||
import com.tuoheng.mapper.AuthoritiesMapper; | |||
import com.tuoheng.mapper.ClientUserMapper; | |||
import com.tuoheng.mapper.ClientUserRoleMapper; | |||
import com.tuoheng.model.dto.LoginUser; | |||
import com.tuoheng.model.param.ClientRoleDto; | |||
import com.tuoheng.model.param.CreateClientUserDto; | |||
import com.tuoheng.model.param.UpdateUserClientRoleDto; | |||
import com.tuoheng.model.param.UpdateUserPassDto; | |||
import com.tuoheng.model.po.AuthoritiesPo; | |||
import com.tuoheng.model.po.ClientUserRolePo; | |||
import com.tuoheng.model.po.UserPo; | |||
import com.tuoheng.service.ClientUserSevice; | |||
import com.tuoheng.until.JsonResult; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | |||
import org.springframework.stereotype.Service; | |||
import org.springframework.transaction.annotation.Transactional; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/8 11:35 | |||
*/ | |||
@Service | |||
public class ClientUserServiceImpl implements ClientUserSevice { | |||
@Autowired | |||
private ClientUserMapper clientUserMapper; | |||
@Autowired | |||
private AuthoritiesMapper authoritiesMapper; | |||
@Autowired | |||
private ClientUserRoleMapper clientUserRoleMapper; | |||
@Transactional(readOnly = true) | |||
public JsonResult judgeCreate(String username){ | |||
if(clientUserMapper.judgeCreateByUserName(username) > 0){ | |||
return JsonResult.success(false); | |||
} | |||
return JsonResult.success(true); | |||
} | |||
@Transactional(rollbackFor = Exception.class) | |||
public JsonResult createClientUser(CreateClientUserDto createClientUserDto, LoginUser loginUser){ | |||
if(clientUserMapper.judgeCreateByUserName(createClientUserDto.getUsername()) > 0){ | |||
return JsonResult.error("该用户名称已存在!"); | |||
} | |||
UserPo userPo = new UserPo() | |||
.setUsername(createClientUserDto.getUsername()) | |||
.setPassword("{bcrypt}" + new BCryptPasswordEncoder().encode(createClientUserDto.getPassword())); | |||
userPo.setCreateUser(loginUser.getUserId()); | |||
clientUserMapper.insertClientUser(userPo); | |||
List<AuthoritiesPo> authoritiesPos = new ArrayList<>(); | |||
List<ClientUserRolePo> clientUserRolePoArrayList = new ArrayList<>(); | |||
for(ClientRoleDto clientRoleDto : createClientUserDto.getClientRoleDtoList()){ | |||
AuthoritiesPo authoritiesPo = new AuthoritiesPo() | |||
.setUserId(userPo.getId()) | |||
.setUsername(createClientUserDto.getUsername()) | |||
.setAuthority(clientRoleDto.getClientId()); | |||
authoritiesPo.setCreateUser(loginUser.getUserId()); | |||
authoritiesPos.add(authoritiesPo); | |||
ClientUserRolePo clientUserRolePo = new ClientUserRolePo() | |||
.setUserId(userPo.getId()) | |||
.setClientId(clientRoleDto.getClientId()) | |||
.setRoleId(clientRoleDto.getRoleId()); | |||
clientUserRolePo.setCreateUser(loginUser.getUserId()); | |||
clientUserRolePoArrayList.add(clientUserRolePo); | |||
} | |||
authoritiesMapper.batchInsert(authoritiesPos); | |||
clientUserRoleMapper.batchInsert(clientUserRolePoArrayList); | |||
return JsonResult.success(userPo.getId()); | |||
} | |||
@Transactional(rollbackFor = Exception.class) | |||
public JsonResult updateUserPassword(UpdateUserPassDto updateUserPassDto, LoginUser loginUser){ | |||
if(clientUserMapper.getUserByUserName(updateUserPassDto.getUsername()) == null){ | |||
return JsonResult.error("该用户不存在!"); | |||
} | |||
UserPo userPo = new UserPo() | |||
.setUsername(updateUserPassDto.getUsername()) | |||
.setPassword("{bcrypt}" + new BCryptPasswordEncoder().encode(updateUserPassDto.getPassword())); | |||
userPo.setUpdateUser(loginUser.getUserId()); | |||
clientUserMapper.updatePass(userPo); | |||
return JsonResult.success(true); | |||
} | |||
@Transactional(rollbackFor = Exception.class) | |||
public JsonResult updateUserClientRole(UpdateUserClientRoleDto updateUserClientRoleDto, LoginUser loginUser){ | |||
UserPo userPo = clientUserMapper.getUserByUserName(updateUserClientRoleDto.getUsername()); | |||
if(userPo == null){ | |||
return JsonResult.error("该用户不存在!"); | |||
} | |||
List<ClientRoleDto> clientRoleDtoList = updateUserClientRoleDto.getClientRoleDtoList(); | |||
for(ClientRoleDto dto : clientRoleDtoList){ | |||
ClientUserRolePo clientUserRolePo = new ClientUserRolePo() | |||
.setUserId(userPo.getId()) | |||
.setClientId(dto.getClientId()) | |||
.setRoleId(dto.getRoleId()); | |||
clientUserRolePo.setUpdateUser(loginUser.getUserId()); | |||
clientUserRoleMapper.updateUserClientRole(clientUserRolePo); | |||
} | |||
return JsonResult.success(true); | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
package com.tuoheng.until; | |||
import org.apache.tomcat.util.codec.binary.Base64; | |||
import javax.crypto.KeyGenerator; | |||
import javax.crypto.SecretKey; | |||
import java.security.NoSuchAlgorithmException; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/9/30 10:56 | |||
*/ | |||
public class CryptoUtil { | |||
public static String genAesSecret() { | |||
try { | |||
KeyGenerator kg = KeyGenerator.getInstance("AES"); | |||
//下面调用方法的参数决定了生成密钥的长度,可以修改为128, 192或256 | |||
kg.init(128); | |||
SecretKey sk = kg.generateKey(); | |||
byte[] b = sk.getEncoded(); | |||
String secret = Base64.encodeBase64String(b); | |||
return secret; | |||
} catch (NoSuchAlgorithmException e) { | |||
e.printStackTrace(); | |||
throw new RuntimeException("没有此算法"); | |||
} | |||
} | |||
} |
@@ -0,0 +1,64 @@ | |||
package com.tuoheng.until; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import java.io.UnsupportedEncodingException; | |||
import java.net.URLDecoder; | |||
import java.net.URLEncoder; | |||
import java.nio.charset.StandardCharsets; | |||
import java.util.Base64; | |||
/** | |||
* 加密工具类 | |||
* @Author: rosh | |||
*/ | |||
public final class EncryptUtil { | |||
private EncryptUtil() { | |||
} | |||
private static final Logger logger = LoggerFactory.getLogger(EncryptUtil.class); | |||
public static String encodeBase64(byte[] bytes) { | |||
return Base64.getEncoder().encodeToString(bytes); | |||
} | |||
public static byte[] decodeBase64(String str) { | |||
return Base64.getDecoder().decode(str); | |||
} | |||
public static String encodeUTF8StringBase64(String str) { | |||
return Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8)); | |||
} | |||
public static String decodeUTF8StringBase64(String str) { | |||
byte[] bytes = Base64.getDecoder().decode(str); | |||
return new String(bytes, StandardCharsets.UTF_8); | |||
} | |||
public static String encodeURL(String url) { | |||
String encoded = null; | |||
try { | |||
encoded = URLEncoder.encode(url, String.valueOf(StandardCharsets.UTF_8)); | |||
} catch (UnsupportedEncodingException e) { | |||
logger.warn("URLEncode失败", e); | |||
} | |||
return encoded; | |||
} | |||
public static String decodeURL(String url) { | |||
String decoded = null; | |||
try { | |||
decoded = URLDecoder.decode(url, String.valueOf(StandardCharsets.UTF_8)); | |||
} catch (UnsupportedEncodingException e) { | |||
logger.warn("URLDecode失败", e); | |||
} | |||
return decoded; | |||
} | |||
} |
@@ -0,0 +1,99 @@ | |||
package com.tuoheng.until; | |||
import java.io.Serializable; | |||
/** | |||
* JSON回应类 | |||
* | |||
* @author 牧羊人 | |||
* @date 2019/11/28 | |||
*/ | |||
public class JsonResult<T> implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 成功 | |||
*/ | |||
public static final int SUCCESS = 0; | |||
/** | |||
* 失败 | |||
*/ | |||
public static final int ERROR = -1; | |||
private int code; | |||
private String msg; | |||
private T data; | |||
public static <T> JsonResult<T> success() { | |||
return jsonResult(null, SUCCESS, "操作成功"); | |||
} | |||
public static <T> JsonResult<T> success(String msg) { | |||
return jsonResult(null, SUCCESS, msg); | |||
} | |||
public static <T> JsonResult<T> success(T data) { | |||
return jsonResult(data, SUCCESS, "操作成功"); | |||
} | |||
public static <T> JsonResult<T> success(T data, String msg) { | |||
return jsonResult(data, SUCCESS, msg); | |||
} | |||
public static <T> JsonResult<T> error() { | |||
return jsonResult(null, ERROR, "操作失败"); | |||
} | |||
public static <T> JsonResult<T> error(String msg) { | |||
return jsonResult(null, ERROR, msg); | |||
} | |||
public static <T> JsonResult<T> error(T data) { | |||
return jsonResult(data, ERROR, "操作失败"); | |||
} | |||
public static <T> JsonResult<T> error(T data, String msg) { | |||
return jsonResult(data, ERROR, msg); | |||
} | |||
public static <T> JsonResult<T> error(int code, String msg) { | |||
return jsonResult(null, code, msg); | |||
} | |||
private static <T> JsonResult<T> jsonResult(T data, int code, String msg) { | |||
JsonResult<T> result = new JsonResult<>(); | |||
result.setCode(code); | |||
result.setData(data); | |||
result.setMsg(msg); | |||
return result; | |||
} | |||
public int getCode() { | |||
return code; | |||
} | |||
public void setCode(int code) { | |||
this.code = code; | |||
} | |||
public String getMsg() { | |||
return msg; | |||
} | |||
public void setMsg(String msg) { | |||
this.msg = msg; | |||
} | |||
public T getData() { | |||
return data; | |||
} | |||
public void setData(T data) { | |||
this.data = data; | |||
} | |||
} |
@@ -0,0 +1,177 @@ | |||
package com.tuoheng.until; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.data.redis.core.StringRedisTemplate; | |||
import org.springframework.stereotype.Component; | |||
import javax.annotation.PostConstruct; | |||
import java.util.HashMap; | |||
import java.util.Set; | |||
import java.util.concurrent.TimeUnit; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/12 13:51 | |||
*/ | |||
@Component | |||
public class RedisUtils { | |||
@Autowired | |||
private StringRedisTemplate redisTemplate; | |||
private static RedisUtils redisUtils; | |||
/** | |||
* 初始化 | |||
*/ | |||
@PostConstruct | |||
public void init() { | |||
redisUtils = this; | |||
redisUtils.redisTemplate = this.redisTemplate; | |||
} | |||
/** | |||
* 查询key,支持模糊查询 | |||
* | |||
* @param key | |||
*/ | |||
public static Set<String> keys(String key) { | |||
return redisUtils.redisTemplate.keys(key); | |||
} | |||
/** | |||
* 获取值 | |||
* | |||
* @param key | |||
*/ | |||
public static Object get(String key) { | |||
return redisUtils.redisTemplate.opsForValue().get(key); | |||
} | |||
/** | |||
* 设置值 | |||
* | |||
* @param key | |||
* @param value | |||
*/ | |||
public static void set(String key, String value) { | |||
redisUtils.redisTemplate.opsForValue().set(key, value); | |||
} | |||
/** | |||
* 设置值,并设置过期时间 | |||
* | |||
* @param key | |||
* @param value | |||
* @param expire 过期时间,单位秒 | |||
*/ | |||
public static void set(String key, String value, Integer expire) { | |||
redisUtils.redisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS); | |||
} | |||
/** | |||
* 删出key | |||
* | |||
* @param key | |||
*/ | |||
public static void delete(String key) { | |||
redisUtils.redisTemplate.opsForValue().getOperations().delete(key); | |||
} | |||
/** | |||
* 设置对象 | |||
* | |||
* @param key key | |||
* @param hashKey hashKey | |||
* @param object 对象 | |||
*/ | |||
public static void hset(String key, String hashKey, Object object) { | |||
redisUtils.redisTemplate.opsForHash().put(key, hashKey, object); | |||
} | |||
/** | |||
* 设置对象 | |||
* | |||
* @param key key | |||
* @param hashKey hashKey | |||
* @param object 对象 | |||
* @param expire 过期时间,单位秒 | |||
*/ | |||
public static void hset(String key, String hashKey, Object object, Integer expire) { | |||
redisUtils.redisTemplate.opsForHash().put(key, hashKey, object); | |||
redisUtils.redisTemplate.expire(key, expire, TimeUnit.SECONDS); | |||
} | |||
/** | |||
* 设置HashMap | |||
* | |||
* @param key key | |||
* @param map map值 | |||
*/ | |||
public static void hset(String key, HashMap<String, Object> map) { | |||
redisUtils.redisTemplate.opsForHash().putAll(key, map); | |||
} | |||
/** | |||
* key不存在时设置值 | |||
* | |||
* @param key | |||
* @param hashKey | |||
* @param object | |||
*/ | |||
public static void hsetAbsent(String key, String hashKey, Object object) { | |||
redisUtils.redisTemplate.opsForHash().putIfAbsent(key, hashKey, object); | |||
} | |||
/** | |||
* 获取Hash值 | |||
* | |||
* @param key | |||
* @param hashKey | |||
* @return | |||
*/ | |||
public static Object hget(String key, String hashKey) { | |||
return redisUtils.redisTemplate.opsForHash().get(key, hashKey); | |||
} | |||
/** | |||
* 获取key的所有值 | |||
* | |||
* @param key | |||
* @return | |||
*/ | |||
public static Object hget(String key) { | |||
return redisUtils.redisTemplate.opsForHash().entries(key); | |||
} | |||
/** | |||
* 删除key的所有值 | |||
* | |||
* @param key | |||
*/ | |||
public static void deleteKey(String key) { | |||
redisUtils.redisTemplate.opsForHash().getOperations().delete(key); | |||
} | |||
/** | |||
* 判断key下是否有值 | |||
* | |||
* @param key | |||
*/ | |||
public static Boolean hasKey(String key) { | |||
return redisUtils.redisTemplate.opsForHash().getOperations().hasKey(key); | |||
} | |||
/** | |||
* 判断key和hasKey下是否有值 | |||
* | |||
* @param key | |||
* @param hasKey | |||
*/ | |||
public static Boolean hasKey(String key, String hasKey) { | |||
return redisUtils.redisTemplate.opsForHash().hasKey(key, hasKey); | |||
} | |||
} | |||
@@ -0,0 +1,68 @@ | |||
spring: | |||
# 注册中心consul地址 | |||
cloud: | |||
consul: | |||
host: 192.168.11.13 # consul 所在服务地址 | |||
port: 8500 # consul 服务端口 | |||
discovery: | |||
## consul ip地址 | |||
hostname: 192.168.11.13 | |||
# 注册到consul的服务名称 | |||
service-name: ${spring.application.name} # 服务提供者名称 | |||
instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port} #实例ID | |||
heartbeat: | |||
enabled: true | |||
prefer-ip-address: true | |||
health-check-path: /actuator/health #健康检查 | |||
health-check-interval: 10s | |||
# 配置数据源 | |||
datasource: | |||
# 使用阿里的Druid连接池 | |||
type: com.alibaba.druid.pool.DruidDataSource | |||
driver-class-name: com.mysql.cj.jdbc.Driver | |||
# 填写你数据库的url、登录名、密码和数据库名 | |||
url: jdbc:mysql://192.168.11.13:3306/tuoheng_oidc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8&useSSL=true&tinyInt1isBit=false | |||
username: root | |||
password: idontcare | |||
druid: | |||
# 连接池的配置信息 | |||
# 初始连接数 | |||
initialSize: 5 | |||
# 最小连接池数量 | |||
minIdle: 5 | |||
# 最大连接池数量 | |||
maxActive: 20 | |||
# 配置获取连接等待超时的时间 | |||
maxWait: 60000 | |||
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 | |||
timeBetweenEvictionRunsMillis: 60000 | |||
# 配置一个连接在池中最小生存的时间,单位是毫秒 | |||
minEvictableIdleTimeMillis: 300000 | |||
# 配置一个连接在池中最大生存的时间,单位是毫秒 | |||
maxEvictableIdleTimeMillis: 900000 | |||
# 配置检测连接是否有效 | |||
validationQuery: SELECT 1 FROM DUAL | |||
testWhileIdle: true | |||
testOnBorrow: false | |||
testOnReturn: false | |||
# Redis数据源 | |||
redis: | |||
# 缓存库默认索引0 | |||
database: 0 | |||
# Redis服务器地址 | |||
host: 192.168.11.13 | |||
# Redis服务器连接端口 | |||
port: 6379 | |||
# Redis服务器连接密码(默认为空) | |||
password: | |||
# 连接超时时间(毫秒) | |||
timeout: 6000 | |||
# 默认的数据过期时间,主要用于shiro权限管理 | |||
expire: 2592000 | |||
jedis: | |||
pool: | |||
max-active: 1000 # 连接池最大连接数(使用负值表示没有限制) | |||
max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制) | |||
max-idle: 10 # 连接池中的最大空闲连接 | |||
min-idle: 1 # 连接池中的最小空闲连接 |
@@ -0,0 +1,67 @@ | |||
spring: | |||
# 注册中心consul地址 | |||
cloud: | |||
consul: | |||
host: 127.0.0.1 # consul 所在服务地址 | |||
port: 8500 # consul 服务端口 | |||
discovery: | |||
## consul ip地址 | |||
hostname: 127.0.0.1 | |||
# 注册到consul的服务名称 | |||
service-name: ${spring.application.name} # 服务提供者名称 | |||
instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port} #实例ID | |||
heartbeat: | |||
enabled: true | |||
prefer-ip-address: true | |||
health-check-path: /actuator/health #健康检查 | |||
health-check-interval: 10s | |||
# 配置数据源 | |||
datasource: | |||
# 使用阿里的Druid连接池 | |||
type: com.alibaba.druid.pool.DruidDataSource | |||
driver-class-name: com.mysql.cj.jdbc.Driver | |||
# 填写你数据库的url、登录名、密码和数据库名 | |||
url: jdbc:mysql://192.168.11.13:3306/tuoheng_oidc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8&useSSL=true&tinyInt1isBit=false | |||
username: root | |||
password: idontcare | |||
druid: | |||
# 连接池的配置信息 | |||
# 初始连接数 | |||
initialSize: 5 | |||
# 最小连接池数量 | |||
minIdle: 5 | |||
# 最大连接池数量 | |||
maxActive: 20 | |||
# 配置获取连接等待超时的时间 | |||
maxWait: 60000 | |||
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 | |||
timeBetweenEvictionRunsMillis: 60000 | |||
# 配置一个连接在池中最小生存的时间,单位是毫秒 | |||
minEvictableIdleTimeMillis: 300000 | |||
# 配置一个连接在池中最大生存的时间,单位是毫秒 | |||
maxEvictableIdleTimeMillis: 900000 | |||
# 配置检测连接是否有效 | |||
validationQuery: SELECT 1 FROM DUAL | |||
testWhileIdle: true | |||
testOnBorrow: false | |||
testOnReturn: false | |||
# Redis数据源 | |||
redis: | |||
# 缓存库默认索引0 | |||
database: 0 | |||
# Redis服务器地址 | |||
host: 192.168.11.13 | |||
# Redis服务器连接端口 | |||
port: 6379 | |||
# Redis服务器连接密码(默认为空) | |||
password: | |||
# 连接超时时间(毫秒) | |||
timeout: 6000 | |||
# 默认的数据过期时间,主要用于shiro权限管理 | |||
expire: 2592000 | |||
jedis: | |||
pool: | |||
max-active: 1000 # 连接池最大连接数(使用负值表示没有限制) | |||
max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制) | |||
max-idle: 10 # 连接池中的最大空闲连接 | |||
min-idle: 1 # 连接池中的最小空闲连接 |
@@ -0,0 +1,70 @@ | |||
spring: | |||
# 注册中心consul地址 | |||
cloud: | |||
consul: | |||
host: 172.16.1.31 # consul 所在服务地址 | |||
port: 8500 # consul 服务端口 | |||
discovery: | |||
## consul ip地址 | |||
hostname: 172.16.1.31 | |||
# 注册到consul的服务名称 | |||
service-name: ${spring.application.name} # 服务提供者名称 | |||
instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port} #实例ID | |||
heartbeat: | |||
enabled: true | |||
prefer-ip-address: true | |||
health-check-path: /actuator/health #健康检查 | |||
health-check-interval: 10s | |||
# 配置数据源 | |||
datasource: | |||
# 使用阿里的Druid连接池 | |||
type: com.alibaba.druid.pool.DruidDataSource | |||
driver-class-name: com.mysql.cj.jdbc.Driver | |||
# 填写你数据库的url、登录名、密码和数据库名 | |||
url: jdbc:mysql://rm-uf6x76i111rb1eo48.mysql.rds.aliyuncs.com:3306/tuoheng_dsp?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8&useSSL=true&tinyInt1isBit=false | |||
username: root | |||
password: TH22#2022 | |||
druid: | |||
# 连接池的配置信息 | |||
# 初始连接数 | |||
initialSize: 5 | |||
# 最小连接池数量 | |||
minIdle: 5 | |||
# 最大连接池数量 | |||
maxActive: 20 | |||
# 配置获取连接等待超时的时间 | |||
maxWait: 60000 | |||
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 | |||
timeBetweenEvictionRunsMillis: 60000 | |||
# 配置一个连接在池中最小生存的时间,单位是毫秒 | |||
minEvictableIdleTimeMillis: 300000 | |||
# 配置一个连接在池中最大生存的时间,单位是毫秒 | |||
maxEvictableIdleTimeMillis: 900000 | |||
# 配置检测连接是否有效 | |||
validationQuery: SELECT 1 FROM DUAL | |||
testWhileIdle: true | |||
testOnBorrow: false | |||
testOnReturn: false | |||
# Redis数据源 | |||
redis: | |||
# 缓存库默认索引0 | |||
database: 0 | |||
# Redis服务器地址 | |||
host: r-uf6r5lm7c7sfdv3ehb.redis.rds.aliyuncs.com | |||
# Redis服务器连接端口 | |||
port: 6379 | |||
# Redis服务器连接密码(默认为空) | |||
password: | |||
# 连接超时时间(毫秒) | |||
timeout: 6000 | |||
# 默认的数据过期时间,主要用于shiro权限管理 | |||
expire: 2592000 | |||
jedis: | |||
pool: | |||
max-active: 1000 # 连接池最大连接数(使用负值表示没有限制) | |||
max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制) | |||
max-idle: 10 # 连接池中的最大空闲连接 | |||
min-idle: 1 # 连接池中的最小空闲连接 | |||
oauth2: | |||
token: | |||
issuer: http://172.16.1.31:8090 |
@@ -0,0 +1,67 @@ | |||
spring: | |||
# 注册中心consul地址 | |||
cloud: | |||
consul: | |||
host: 192.168.11.242 # consul 所在服务地址 | |||
port: 8500 # consul 服务端口 | |||
discovery: | |||
## consul ip地址 | |||
hostname: 192.168.11.242 | |||
# 注册到consul的服务名称 | |||
service-name: ${spring.application.name} # 服务提供者名称 | |||
instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port} #实例ID | |||
heartbeat: | |||
enabled: true | |||
prefer-ip-address: true | |||
health-check-path: /actuator/health #健康检查 | |||
health-check-interval: 10s | |||
# 配置数据源 | |||
datasource: | |||
# 使用阿里的Druid连接池 | |||
type: com.alibaba.druid.pool.DruidDataSource | |||
driver-class-name: com.mysql.cj.jdbc.Driver | |||
# 填写你数据库的url、登录名、密码和数据库名 | |||
url: jdbc:mysql://192.168.11.242:3306/tuoheng_oidc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8&useSSL=true&tinyInt1isBit=false | |||
username: root | |||
password: idontcare | |||
druid: | |||
# 连接池的配置信息 | |||
# 初始连接数 | |||
initialSize: 5 | |||
# 最小连接池数量 | |||
minIdle: 5 | |||
# 最大连接池数量 | |||
maxActive: 20 | |||
# 配置获取连接等待超时的时间 | |||
maxWait: 60000 | |||
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 | |||
timeBetweenEvictionRunsMillis: 60000 | |||
# 配置一个连接在池中最小生存的时间,单位是毫秒 | |||
minEvictableIdleTimeMillis: 300000 | |||
# 配置一个连接在池中最大生存的时间,单位是毫秒 | |||
maxEvictableIdleTimeMillis: 900000 | |||
# 配置检测连接是否有效 | |||
validationQuery: SELECT 1 FROM DUAL | |||
testWhileIdle: true | |||
testOnBorrow: false | |||
testOnReturn: false | |||
# Redis数据源 | |||
redis: | |||
# 缓存库默认索引0 | |||
database: 0 | |||
# Redis服务器地址 | |||
host: 192.168.11.242 | |||
# Redis服务器连接端口 | |||
port: 6379 | |||
# Redis服务器连接密码(默认为空) | |||
password: | |||
# 连接超时时间(毫秒) | |||
timeout: 6000 | |||
# 默认的数据过期时间,主要用于shiro权限管理 | |||
expire: 2592000 | |||
jedis: | |||
pool: | |||
max-active: 1000 # 连接池最大连接数(使用负值表示没有限制) | |||
max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制) | |||
max-idle: 10 # 连接池中的最大空闲连接 | |||
min-idle: 1 # 连接池中的最小空闲连接 |
@@ -0,0 +1,13 @@ | |||
server: | |||
port: 8091 | |||
spring: | |||
profiles: | |||
active: @package.environment@ | |||
application: | |||
name: tuoheng-oidc-admin | |||
main: | |||
allow-bean-definition-overriding: true | |||
mybatis: | |||
mapper-locations: classpath*:mapper/*Mapper.xml |
@@ -0,0 +1,69 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 --> | |||
<!-- scan:当此属性设置为true时,配置文档如果发生改变,将会被重新加载,默认值为true --> | |||
<!-- scanPeriod:设置监测配置文档是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。 | |||
当scan为true时,此属性生效。默认的时间间隔为1分钟。 --> | |||
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 --> | |||
<configuration scan="true" scanPeriod="60 seconds" debug="false"> | |||
<!-- | |||
contextName说明: | |||
每个logger都关联到logger上下文,默认上下文名称为“default”。但可以使用设置成其他名字, | |||
用于区分不同应用程序的记录。一旦设置,不能修改,可以通过%contextName来打印日志上下文名称。 | |||
--> | |||
<contextName>tuoheng_oidc_admin</contextName> | |||
<!--定义日志变量--> | |||
<!--<property name="logging.path" value="D:\\idealogs\\tuoheng_oidc"/>--> | |||
<property name="logging.path" value="/data/java/logs/tuoheng_oidc"/> | |||
<!--日志格式: [时间] [级别] [线程] [行号] [logger信息] - [日志信息]--> | |||
<property name="logging.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%level][%thread][%L] %logger - %msg%n"/> | |||
<property name="logging.charset" value="UTF-8"/> | |||
<property name="logging.maxHistory" value="15"/> | |||
<property name="logging.totalSizeCap" value="5GB"/> | |||
<property name="logging.maxFileSize" value="40MB"/> | |||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> | |||
<encoder> | |||
<pattern>${logging.pattern}</pattern> | |||
<charset>${logging.charset}</charset> | |||
</encoder> | |||
</appender> | |||
<appender name="LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> | |||
<File>${logging.path}/admin/tuoheng_oidc_admin.log</File> | |||
<append>true</append> | |||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> | |||
<fileNamePattern>${logging.path}/admin/tuoheng_oidc_admin-%d-%i.log</fileNamePattern> | |||
<!-- 最大保存天数--> | |||
<maxHistory>${logging.maxHistory}</maxHistory> | |||
<totalSizeCap>${logging.totalSizeCap}</totalSizeCap> | |||
<maxFileSize>${logging.maxFileSize}</maxFileSize> | |||
</rollingPolicy> | |||
<!--编码器--> | |||
<encoder> | |||
<pattern>${logging.pattern}</pattern> | |||
<charset>${logging.charset}</charset> | |||
</encoder> | |||
</appender> | |||
<appender name="file.async" class="ch.qos.logback.classic.AsyncAppender"> | |||
<discardingThreshold>0</discardingThreshold> | |||
<queueSize>512</queueSize> | |||
<includeCallerData>true</includeCallerData> | |||
<appender-ref ref="LOG_FILE" /> | |||
</appender> | |||
<logger name="com.tuoheng" level="DEBUG" additivity="false"> | |||
<appender-ref ref="console" /> | |||
<appender-ref ref="file.async" /> | |||
</logger> | |||
<!--log4jdbc --> | |||
<logger name="jdbc.sqltiming" level="DEBUG" additivity="false"> | |||
<appender-ref ref="file.async" /> | |||
</logger> | |||
<root level="INFO"> | |||
<appender-ref ref="console" /> | |||
<appender-ref ref="file.async" /> | |||
</root> | |||
</configuration> |
@@ -0,0 +1,13 @@ | |||
<?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.tuoheng.mapper.AuthoritiesMapper"> | |||
<insert id="batchInsert" parameterType="java.util.List"> | |||
insert into authorities (user_id, username, authority, create_user) | |||
VALUES | |||
<foreach collection ="list" item="it" separator =","> | |||
(#{it.userId}, #{it.username}, #{it.authority}, #{it.createUser}) | |||
</foreach > | |||
</insert> | |||
</mapper> |
@@ -0,0 +1,32 @@ | |||
<?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.tuoheng.mapper.ClientUserMapper"> | |||
<insert id="insertClientUser" parameterType="com.tuoheng.model.po.UserPo" keyProperty="id" useGeneratedKeys="true"> | |||
insert into users (username, password, create_user) | |||
values (#{username}, #{password}, #{createUser}) | |||
</insert> | |||
<select id="judgeCreateByUserName" parameterType="java.lang.String" resultType="int"> | |||
select count(1) from users where username = #{username} | |||
</select> | |||
<select id="getUserByUserName" parameterType="java.lang.String" resultType="com.tuoheng.model.po.UserPo"> | |||
select * from users where username = #{username} | |||
</select> | |||
<update id="updatePass" parameterType="com.tuoheng.model.po.UserPo"> | |||
update users | |||
<set> | |||
<if test="password != null and password != ''" > | |||
password = #{password}, | |||
</if> | |||
<if test="updateUser != null" > | |||
update_user = #{updateUser}, | |||
</if> | |||
</set> | |||
where username = #{username,jdbcType=VARCHAR} | |||
</update> | |||
</mapper> |
@@ -0,0 +1,26 @@ | |||
<?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.tuoheng.mapper.ClientUserRoleMapper"> | |||
<insert id="batchInsert" parameterType="java.util.List"> | |||
insert into t_client_user_role (user_id, client_id, role_id, create_user) | |||
VALUES | |||
<foreach collection ="list" item="it" separator =","> | |||
(#{it.userId}, #{it.clientId}, #{it.roleId}, #{it.createUser}) | |||
</foreach > | |||
</insert> | |||
<update id="updateUserClientRole" parameterType="com.tuoheng.model.po.ClientUserRolePo"> | |||
update t_client_user_role | |||
<set> | |||
<if test="roleId != null" > | |||
role_id = #{roleId}, | |||
</if> | |||
<if test="updateUser != null" > | |||
update_user = #{updateUser}, | |||
</if> | |||
</set> | |||
where user_id = #{userId} and client_id = #{clientId} | |||
</update> | |||
</mapper> |
@@ -1,5 +1,9 @@ | |||
package com.tuoheng.config; | |||
import com.alibaba.fastjson.JSONObject; | |||
import com.tuoheng.mapper.UserMapper; | |||
import com.tuoheng.model.dto.UserBaseInfoDto; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.context.annotation.Bean; | |||
import org.springframework.context.annotation.Configuration; | |||
import org.springframework.security.core.GrantedAuthority; | |||
@@ -21,6 +25,9 @@ import java.util.stream.Collectors; | |||
@Configuration(proxyBeanMethods = false) | |||
public class IdTokenCustomizerConfig { | |||
@Autowired | |||
private UserMapper userMapper; | |||
@Bean | |||
public OAuth2TokenCustomizer<JwtEncodingContext> tokenCustomizer() { | |||
return (context) -> { | |||
@@ -31,10 +38,17 @@ public class IdTokenCustomizerConfig { | |||
.collect(Collectors.toSet()))); | |||
} | |||
if ("access_token".equals(context.getTokenType().getValue())) { | |||
UserBaseInfoDto userBaseInfoDto = userMapper.getUserBaseInfo(context.getPrincipal().getName()); | |||
context.getClaims().claims(claims -> | |||
claims.put("scope", context.getPrincipal().getAuthorities() | |||
.stream().map(GrantedAuthority::getAuthority) | |||
.collect(Collectors.toSet()))); | |||
.collect(Collectors.toSet()))) | |||
.claims(claims -> | |||
claims.put("username", context.getPrincipal().getName())) | |||
.claims(claims -> | |||
claims.put("oUserId", userBaseInfoDto.getUserId())) | |||
.claims(claims -> | |||
claims.put("clientRoleList", JSONObject.toJSONString(userBaseInfoDto.getClientRoleDtoList()))); | |||
} | |||
}; | |||
} |
@@ -0,0 +1,17 @@ | |||
package com.tuoheng.model.dto; | |||
import lombok.Data; | |||
/** | |||
* @author chenjiandong | |||
* @description: TODO | |||
* @date 2022/10/26 11:33 | |||
*/ | |||
@Data | |||
public class ClientRoleDto { | |||
private String clientId; | |||
private Integer roleId; | |||
} |
@@ -18,6 +18,14 @@ public class UserBaseInfoDto { | |||
private String password; | |||
/** | |||
* 可以访问的 client | |||
*/ | |||
private List<String> authorityList; | |||
/** | |||
* 可以访问的 client 以及 role | |||
*/ | |||
private List<ClientRoleDto> clientRoleDtoList; | |||
} |
@@ -31,7 +31,8 @@ public class OidcUserInfoServiceImpl implements OidcUserInfoService { | |||
if (scopes.contains(OidcScopes.PROFILE)) { | |||
builder.claim("userId", userBaseInfoDto.getUserId()) | |||
.claim("userName", userBaseInfoDto.getUserName()) | |||
.claim("authority", userBaseInfoDto.getAuthorityList()); | |||
.claim("authority", userBaseInfoDto.getAuthorityList()) | |||
.claim("clientRoleList", userBaseInfoDto.getClientRoleDtoList()); | |||
} | |||
/*if (scopes.contains(OidcScopes.EMAIL)) { | |||
builder.email(name + "@163.com").emailVerified(true); |
@@ -62,6 +62,7 @@ public class UserServiceImpl implements UserSevice { | |||
@Override | |||
public JsonResult getUserInfo(GetUserInfoDto getUserInfoDto){ | |||
UserBaseInfoDto userBaseInfoDto = userMapper.getMpUserInfo(getUserInfoDto.getUsername()); | |||
return JsonResult.success(userBaseInfoDto); | |||
} | |||
@@ -3,8 +3,8 @@ spring: | |||
oauth2: | |||
resource-server: | |||
jwt: | |||
#issuer-uri: http://192.168.11.11:8090 #认证中心端点,作为资源端的配置 | |||
issuer-uri: http://oidc.dev.t-aaron.com | |||
issuer-uri: http://192.168.11.11:8090 #认证中心端点,作为资源端的配置 | |||
#issuer-uri: http://oidc.dev.t-aaron.com | |||
# 配置数据源 | |||
datasource: |
@@ -9,6 +9,10 @@ | |||
<collection property="authorityList" ofType="java.lang.String" javaType="java.util.List"> | |||
<result column="authority" jdbcType="VARCHAR"/> | |||
</collection> | |||
<collection property="clientRoleDtoList" ofType="com.tuoheng.model.dto.ClientRoleDto" javaType="java.util.List"> | |||
<result column="clientId" jdbcType="VARCHAR" property="clientId" /> | |||
<result column="roleId" jdbcType="INTEGER" property="roleId" /> | |||
</collection> | |||
</resultMap> | |||
<insert id="insertUser" parameterType="com.tuoheng.model.po.UserPo" keyProperty="id" useGeneratedKeys="true"> | |||
@@ -16,18 +20,19 @@ | |||
values (#{username}, #{password}) | |||
</insert> | |||
<select id="getUserBaseInfo" resultMap="UserBaseInfoMap"> | |||
select a.id as userId, a.username as userName, a.password , b.authority | |||
select a.id as userId, a.username as userName, a.password , b.authority, c.client_id as clientId, c.role_id as roleId | |||
from users a | |||
inner join authorities b on a.id = b.user_id | |||
left join authorities b on a.id = b.user_id | |||
left join t_client_user_role c on a.id = c.user_id | |||
where a.username = #{username} | |||
</select> | |||
<select id="getMpUserInfo" resultMap="UserBaseInfoMap"> | |||
select a.id as userId, a.username as userName, b.authority | |||
select a.id as userId, a.username as userName, a.password , b.authority, c.client_id as clientId, c.role_id as roleId | |||
from users a | |||
inner join authorities b on a.id = b.user_id | |||
left join authorities b on a.id = b.user_id | |||
left join t_client_user_role c on a.id = c.user_id | |||
where a.username = #{username} | |||
</select> | |||