新增swagger和shardingjdbc

This commit is contained in:
zhuyijun 2022-09-23 01:00:22 +08:00
parent 4d7590a3c9
commit ee32e15a6e
48 changed files with 871 additions and 159 deletions

22
pom.xml
View File

@ -38,12 +38,13 @@
<feign-ribbon.version>11.8</feign-ribbon.version> <feign-ribbon.version>11.8</feign-ribbon.version>
<!-- json解析 --> <!-- json解析 -->
<jackson.version>2.13.3</jackson.version> <jackson.version>2.13.3</jackson.version>
<jackson-datatype-jsr310.version>2.13.3</jackson-datatype-jsr310.version>
<fastjson.version>2.0.11</fastjson.version> <fastjson.version>2.0.11</fastjson.version>
<!-- ORM --> <!-- ORM -->
<mybatis-plus-boot-starter.version>3.4.3</mybatis-plus-boot-starter.version> <mybatis-plus-boot-starter.version>3.4.3</mybatis-plus-boot-starter.version>
<mysql-jdbc.version>8.0.21</mysql-jdbc.version> <mysql-jdbc.version>8.0.21</mysql-jdbc.version>
<postgresql.version>42.5.0</postgresql.version> <postgresql.version>42.5.0</postgresql.version>
<jackson-datatype-jsr310.version>2.13.3</jackson-datatype-jsr310.version> <shardingsphere.version>4.1.1</shardingsphere.version>
<!-- spring-cloud-alibaba版本配置 --> <!-- spring-cloud-alibaba版本配置 -->
<aliyun.version>4.5.0</aliyun.version> <aliyun.version>4.5.0</aliyun.version>
<com.alibaba.transmittable.version>2.12.2</com.alibaba.transmittable.version> <com.alibaba.transmittable.version>2.12.2</com.alibaba.transmittable.version>
@ -65,7 +66,8 @@
<commons-collections4.version>4.4</commons-collections4.version> <commons-collections4.version>4.4</commons-collections4.version>
<commons-io.version>2.11.0</commons-io.version> <commons-io.version>2.11.0</commons-io.version>
<commons-crypto.version>1.1.0</commons-crypto.version> <commons-crypto.version>1.1.0</commons-crypto.version>
<!-- 文档-->
<knife4j.version>3.0.3</knife4j.version>
</properties> </properties>
<dependencyManagement> <dependencyManagement>
@ -122,6 +124,16 @@
<artifactId>mysql-connector-java</artifactId> <artifactId>mysql-connector-java</artifactId>
<version>${mysql-jdbc.version}</version> <version>${mysql-jdbc.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-micro-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<!-- JWT 依赖开始 --> <!-- JWT 依赖开始 -->
<!-- <dependency>--> <!-- <dependency>-->
<!-- <groupId>io.jsonwebtoken</groupId>--> <!-- <groupId>io.jsonwebtoken</groupId>-->
@ -242,6 +254,12 @@
<!-- <artifactId>spring-security-oauth2-authorization-server</artifactId>--> <!-- <artifactId>spring-security-oauth2-authorization-server</artifactId>-->
<!-- <version>${spring-authorization-server.version}</version>--> <!-- <version>${spring-authorization-server.version}</version>-->
<!-- </dependency>--> <!-- </dependency>-->
<!-- https://mvnrepository.com/artifact/org.apache.shardingsphere/shardingsphere-jdbc-core-spring-boot-starter -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>${shardingsphere.version}</version>
</dependency>
</dependencies> </dependencies>

View File

@ -37,7 +37,7 @@
<artifactId>commons-pool2</artifactId> <artifactId>commons-pool2</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<artifactId>zyjblogs-web-spring-boot-starter</artifactId> <artifactId>zyjblogs-common-spring-boot-starter</artifactId>
<groupId>cn.zyjblogs.starter</groupId> <groupId>cn.zyjblogs.starter</groupId>
<exclusions> <exclusions>
<exclusion> <exclusion>
@ -46,11 +46,11 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<!-- 集成redis--> <!-- 集成redis-->
<!-- <dependency>--> <!-- <dependency>-->
<!-- <groupId>cn.zyjblogs.starter</groupId>--> <!-- <groupId>cn.zyjblogs.starter</groupId>-->
<!-- <artifactId>zyjblogs-redis-spring-boot-starter</artifactId>--> <!-- <artifactId>zyjblogs-redis-spring-boot-starter</artifactId>-->
<!-- </dependency>--> <!-- </dependency>-->
<!-- 集成nacos--> <!-- 集成nacos-->
<!-- 集成 Nacos 作为服务注册中心配置 --> <!-- 集成 Nacos 作为服务注册中心配置 -->
@ -85,5 +85,10 @@
<groupId>com.alibaba.csp</groupId> <groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId> <artifactId>sentinel-datasource-nacos</artifactId>
</dependency> </dependency>
<!-- knife4j文档 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -0,0 +1,44 @@
package cn.zyjblogs.config.swagger;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import springfox.documentation.swagger.web.UiConfiguration;
/**
* @author zhuyijun
*/
@RestController
@RequestMapping("/swagger-resources")
public class SwaggerHandler {
private final SwaggerResourcesProvider swaggerResources;
private final UiConfiguration uiConfiguration;
public SwaggerHandler(SwaggerResourcesProvider swaggerResources, UiConfiguration uiConfiguration) {
this.swaggerResources = swaggerResources;
this.uiConfiguration = uiConfiguration;
}
// @GetMapping("/swagger-resources/configuration/security")
// public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
// return Mono.just(new ResponseEntity<>(
// Optional.ofNullable(OAuth2ResourceServerAutoConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
// }
@GetMapping("")
public Mono<ResponseEntity> swaggerResources() {
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
}
@GetMapping("/configuration/ui")
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
return Mono.just(new ResponseEntity<>(uiConfiguration, HttpStatus.OK));
}
}

View File

@ -0,0 +1,66 @@
package cn.zyjblogs.config.swagger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import springfox.documentation.swagger.web.UiConfiguration;
import springfox.documentation.swagger.web.UiConfigurationBuilder;
import java.util.ArrayList;
import java.util.List;
/**
* @author zhuyijun
*/
@Configuration
@Primary
public class SwaggerProvider implements SwaggerResourcesProvider {
public static final String API_URI = "/v2/api-docs";
private final RouteLocator routeLocator;
private final GatewayProperties gatewayProperties;
@Autowired
public SwaggerProvider(RouteLocator routeLocator, GatewayProperties gatewayProperties) {
this.routeLocator = routeLocator;
this.gatewayProperties = gatewayProperties;
}
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();
List<String> routes = new ArrayList<>();
//取出gateway的route
routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
//结合配置的route-路径(Path)和route过滤只获取有效的route节点
gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId()))
.forEach(routeDefinition -> routeDefinition.getPredicates().stream()
.filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()) && predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0").startsWith("/api"))
.forEach(predicateDefinition -> resources.add(swaggerResource(routeDefinition.getId(),
predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0")
.replace("/**", API_URI)))));
return resources;
}
private SwaggerResource swaggerResource(String name, String location) {
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(name);
swaggerResource.setLocation(location);
swaggerResource.setSwaggerVersion("3.0");
return swaggerResource;
}
@Bean
public UiConfiguration uiConfiguration() {
return UiConfigurationBuilder.builder().build();
}
}

View File

@ -1,9 +1,9 @@
package cn.zyjblogs.filter; package cn.zyjblogs.filter;
import cn.zyjblogs.starter.common.entity.constant.HttpHeaderConstant; import cn.zyjblogs.starter.common.entity.constant.HttpHeaderConstant;
import cn.zyjblogs.starter.common.entity.response.HttpCode;
import cn.zyjblogs.starter.common.entity.response.ResponseObject; import cn.zyjblogs.starter.common.entity.response.ResponseObject;
import cn.zyjblogs.starter.common.entity.response.ResponseResult; import cn.zyjblogs.starter.common.entity.response.ResponseResult;
import cn.zyjblogs.starter.common.entity.response.HttpCode;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -11,8 +11,6 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
@ -42,7 +40,6 @@ import java.util.List;
public class AuthFilter implements GlobalFilter { public class AuthFilter implements GlobalFilter {
private final WhiteListProperties whiteListProperties; private final WhiteListProperties whiteListProperties;
private AntPathMatcher antPathMatcher = new AntPathMatcher(); private AntPathMatcher antPathMatcher = new AntPathMatcher();
private String SIGNING_KEY="zyjblogs123";
@Override @Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
@ -54,16 +51,12 @@ public class AuthFilter implements GlobalFilter {
ServerHttpRequest request = build.getRequest(); ServerHttpRequest request = build.getRequest();
ServerHttpResponse response = build.getResponse(); ServerHttpResponse response = build.getResponse();
String token = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION); String token = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
log.debug("token:{}", token);
String path = request.getURI().getPath(); String path = request.getURI().getPath();
String methodType = request.getMethodValue().toLowerCase();
Route route = (Route) exchange.getAttributes().get(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
String routeId = route.getId();
//白名单请求直接放行 //白名单请求直接放行
if (isWhileList(path)) { if (isWhileList(path)) {
return chain.filter(exchange); return chain.filter(exchange);
} }
if (StringUtils.isEmpty(token)) { if (token == null || StringUtils.isEmpty(token) || !token.startsWith(HttpHeaderConstant.AUTHORIZATION_TYPE)) {
return getErrorMono(response, HttpCode.UNAUTHORIZED, "无访问权限"); return getErrorMono(response, HttpCode.UNAUTHORIZED, "无访问权限");
} }
if (isExpired(token)) { if (isExpired(token)) {
@ -93,15 +86,19 @@ public class AuthFilter implements GlobalFilter {
* @date 2021/11/15 19:17 * @date 2021/11/15 19:17
*/ */
private boolean isExpired(String token) { private boolean isExpired(String token) {
if (!token.startsWith(HttpHeaderConstant.AUTHORIZATION_TYPE)) { //// String jwt = token.replace(HttpHeaderConstant.AUTHORIZATION_TYPE, "").trim();
return true; // try {
} //// PublicKey publicKeyByPath = RsaUtils.getPublicKeyByPath(rsaKeyProperties.getPubKeyPath());
// String jwt = token.replace(HttpHeaderConstant.AUTHORIZATION_TYPE + " ", ""); //// Claims body = new JwtParsers(false).setSigningKey(publicKeyByPath).parseClaimsJwt(jwt).getBody();
// OauthClaims body = (OauthClaims) Jwts.parser().setSigningKey(SIGNING_KEY).parseClaimsJws(jwt).getBody(); //// log.info("{}", body);
// BaseContextHandler.set(ContextDto.builder().token(jwt).userId(body.getUserId()).username(body.getUsername()).build()); // return false;
// } catch (Exception e) {
// return true;
// }
return false; return false;
} }
/** /**
* 是否是白名单 * 是否是白名单
* *
@ -121,7 +118,6 @@ public class AuthFilter implements GlobalFilter {
} }
/** /**
* 验证不通过时的返回 * 验证不通过时的返回
* *

View File

@ -7,6 +7,8 @@ import java.util.List;
/** /**
* 白名单 * 白名单
*
* @author zhuyijun
*/ */
@Data @Data
@ConfigurationProperties(prefix = "zyjblogs.whilelist") @ConfigurationProperties(prefix = "zyjblogs.whilelist")

View File

@ -18,6 +18,7 @@ spring:
shared-configs[0]: shared-configs[0]:
data-id: zyjblogs-global-${spring.profiles.active}.yml data-id: zyjblogs-global-${spring.profiles.active}.yml
group: global group: global
refresh: true
discovery: discovery:
server-addr: ${spring.cloud.nacos.config.server-addr} server-addr: ${spring.cloud.nacos.config.server-addr}
username: ${spring.cloud.nacos.config.username} username: ${spring.cloud.nacos.config.username}

View File

@ -4,6 +4,7 @@ import cn.zyjblogs.config.handler.ResourceAccessDeniedHandler;
import cn.zyjblogs.config.handler.ResourceAuthenticationEntryPoint; import cn.zyjblogs.config.handler.ResourceAuthenticationEntryPoint;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@ -12,14 +13,19 @@ import org.springframework.security.oauth2.config.annotation.web.configuration.R
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.TokenStore;
/**
* @author zhuyijun
*/
@Configuration @Configuration
@EnableResourceServer @EnableResourceServer
@RequiredArgsConstructor @RequiredArgsConstructor
@EnableConfigurationProperties(WhiteListProperties.class)
@RefreshScope @RefreshScope
public class ResourceServerConfig extends ResourceServerConfigurerAdapter { public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Value("${spring.application.name}") @Value("${spring.application.name}")
private String resourceId; private String resourceId;
private final TokenStore tokenStore; private final TokenStore tokenStore;
private final WhiteListProperties whiteListProperties;
@Override @Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception { public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
@ -45,10 +51,12 @@ public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
.csrf() .csrf()
.disable() .disable()
//限制资源服务器作用范围为 "/user/**", "/demo/**" //限制资源服务器作用范围为 "/user/**", "/demo/**"
.requestMatchers().antMatchers("/user/**", "/demo/**").and() .requestMatchers().antMatchers("/webjars/**", "/swagger-ui.html/**", "/swagger-resources/**", "/v2/api-docs/**", "/user/**", "/demo/**",
String.join(",", whiteListProperties.getAllowPaths()))
.and()
.formLogin().and() .formLogin().and()
.authorizeRequests() .authorizeRequests()
.antMatchers("/webjars/**", "/swagger-ui.html/**", "/swagger-resources/**", "/v2/api-docs/**") .antMatchers("/webjars/**", "/swagger-ui.html/**", "/swagger-resources/**", "/v2/api-docs/**", String.join(",", whiteListProperties.getAllowPaths()))
.permitAll() .permitAll()
.antMatchers("/login", "/oauth/**", "/user/login", "/user/refresh/token").permitAll() .antMatchers("/login", "/oauth/**", "/user/login", "/user/refresh/token").permitAll()
//以下请求必须认证通过 //以下请求必须认证通过

View File

@ -0,0 +1,18 @@
package cn.zyjblogs.config.security;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.List;
/**
* 白名单
*
* @author zhuyijun
*/
@Data
@ConfigurationProperties(prefix = "zyjblogs.whilelist")
public class WhiteListProperties {
private List<String> allowPaths;
}

View File

@ -6,6 +6,7 @@ import cn.zyjblogs.server.user.service.AuthService;
import cn.zyjblogs.server.user.vo.OAuth2AccessTokenVo; import cn.zyjblogs.server.user.vo.OAuth2AccessTokenVo;
import cn.zyjblogs.starter.common.entity.response.ResponseObject; import cn.zyjblogs.starter.common.entity.response.ResponseObject;
import cn.zyjblogs.starter.common.entity.response.ResponseResult; import cn.zyjblogs.starter.common.entity.response.ResponseResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -17,10 +18,11 @@ import org.springframework.web.bind.annotation.RestController;
/** /**
* @author zhuyijun * @author zhuyijun
*/ */
@Api(tags = {"token管理"})
@RestController @RestController
@RequiredArgsConstructor @RequiredArgsConstructor
@RequestMapping("/auth") @RequestMapping("/auth")
public class AutoController { public class AuthController {
private final AuthService authService; private final AuthService authService;
@ApiOperation(value = "刷新token", notes = "刷新token") @ApiOperation(value = "刷新token", notes = "刷新token")

View File

@ -5,6 +5,7 @@ import cn.zyjblogs.server.user.service.LoginService;
import cn.zyjblogs.server.user.vo.OAuth2AccessTokenVo; import cn.zyjblogs.server.user.vo.OAuth2AccessTokenVo;
import cn.zyjblogs.starter.common.entity.response.ResponseObject; import cn.zyjblogs.starter.common.entity.response.ResponseObject;
import cn.zyjblogs.starter.common.entity.response.ResponseResult; import cn.zyjblogs.starter.common.entity.response.ResponseResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -16,6 +17,7 @@ import org.springframework.web.bind.annotation.RestController;
/** /**
* @author zhuyijun * @author zhuyijun
*/ */
@Api(tags = {"登录认证管理"})
@RestController @RestController
@RequiredArgsConstructor @RequiredArgsConstructor
@RequestMapping("/user") @RequestMapping("/user")

View File

@ -21,6 +21,7 @@ spring:
shared-configs[0]: shared-configs[0]:
data-id: zyjblogs-global-${spring.profiles.active}.yml data-id: zyjblogs-global-${spring.profiles.active}.yml
group: global group: global
refresh: true
discovery: discovery:
server-addr: ${spring.cloud.nacos.config.server-addr} server-addr: ${spring.cloud.nacos.config.server-addr}
username: ${spring.cloud.nacos.config.username} username: ${spring.cloud.nacos.config.username}

View File

@ -8,6 +8,8 @@ import cn.zyjblogs.starter.common.entity.response.ResponseObject;
import cn.zyjblogs.starter.common.entity.response.ResponseResult; import cn.zyjblogs.starter.common.entity.response.ResponseResult;
import cn.zyjblogs.starter.common.utils.bean.BeanUtils; import cn.zyjblogs.starter.common.utils.bean.BeanUtils;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -21,6 +23,7 @@ import java.util.List;
/** /**
* @author zhuyijun * @author zhuyijun
*/ */
@Api(tags = {"角色管理"})
@RestController @RestController
@RequestMapping("/role") @RequestMapping("/role")
@ResponseBody @ResponseBody
@ -36,6 +39,7 @@ public class RoleController {
* @author zhuyijun * @author zhuyijun
* @date 2022/9/19 上午12:06 * @date 2022/9/19 上午12:06
*/ */
@ApiOperation(value = "1", notes = "通过id查询用户")
@GetMapping("/id") @GetMapping("/id")
public ResponseObject<RoleVo> findById(@RequestParam String id) { public ResponseObject<RoleVo> findById(@RequestParam String id) {
RolePo byId = roleService.getById(id); RolePo byId = roleService.getById(id);
@ -49,12 +53,25 @@ public class RoleController {
* @author zhuyijun * @author zhuyijun
* @date 2022/9/19 上午1:14 * @date 2022/9/19 上午1:14
*/ */
@ApiOperation(value = "page=1&limit=10", notes = "分页查询")
@GetMapping("/page") @GetMapping("/page")
public ResponseObject<List<RoleVo>> findPage(RolePageDto rolePageDto) { public ResponseObject<List<RoleVo>> findPage(RolePageDto rolePageDto) {
IPage<RoleVo> page = roleService.findPage(rolePageDto); IPage<RoleVo> page = roleService.findPage(rolePageDto);
return ResponseResult.success(page.getTotal(), page.getRecords()); return ResponseResult.success(page.getTotal(), page.getRecords());
} }
/**
* @param
* @return cn.zyjblogs.starter.common.entity.response.ResponseObject<java.util.List < cn.zyjblogs.server.role.vo.RoleVo>>
* @author zhuyijun
* @date 2022/9/22 下午11:33
*/
@ApiOperation(value = "", notes = "查询所有角色")
@GetMapping("/list")
public ResponseObject<List<RoleVo>> findList() {
return ResponseResult.success(roleService.findList());
}
/** /**
* 通过id集合查询 * 通过id集合查询
* *
@ -63,6 +80,7 @@ public class RoleController {
* @author zhuyijun * @author zhuyijun
* @date 2022/9/19 上午1:14 * @date 2022/9/19 上午1:14
*/ */
@ApiOperation(value = "1", notes = "通过角色id查询")
@PostMapping("/findByIds") @PostMapping("/findByIds")
public ResponseObject<List<RoleVo>> findByIds(List<String> ids) { public ResponseObject<List<RoleVo>> findByIds(List<String> ids) {
return ResponseResult.success(roleService.findByIds(ids)); return ResponseResult.success(roleService.findByIds(ids));

View File

@ -1,7 +1,13 @@
package cn.zyjblogs.server.role.dto; package cn.zyjblogs.server.role.dto;
import cn.zyjblogs.starter.common.entity.constant.CommonConstant;
import cn.zyjblogs.starter.common.entity.dto.PageDto; import cn.zyjblogs.starter.common.entity.dto.PageDto;
import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
@ -28,12 +34,18 @@ public class RolePageDto extends PageDto implements Serializable {
private String createUserId; private String createUserId;
@JSONField(format = "yyyy-MM-dd HH:mm:ss") @JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JSONField(format = CommonConstant.DATETIME_PATTERN)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = CommonConstant.DATETIME_PATTERN)
private LocalDateTime createTime; private LocalDateTime createTime;
private String editUserId; private String editUserId;
@JSONField(format = "yyyy-MM-dd HH:mm:ss") @JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JSONField(format = CommonConstant.DATETIME_PATTERN)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = CommonConstant.DATETIME_PATTERN)
private LocalDateTime editTime; private LocalDateTime editTime;
private String tenantId; private String tenantId;

View File

@ -1,11 +1,12 @@
package cn.zyjblogs.server.role.po; package cn.zyjblogs.server.role.po;
import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
@ -40,6 +41,7 @@ public class RolePo implements Serializable {
private String createUserId; private String createUserId;
@JsonSerialize(using = LocalDateTimeSerializer.class) @JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@TableField("create_time") @TableField("create_time")
private LocalDateTime createTime; private LocalDateTime createTime;
@ -48,9 +50,11 @@ public class RolePo implements Serializable {
private String editUserId; private String editUserId;
@JsonSerialize(using = LocalDateTimeSerializer.class) @JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@TableField("edit_time") @TableField("edit_time")
private LocalDateTime editTime; private LocalDateTime editTime;
@TableField("tenant_id") @TableField("tenant_id")
private String tenantId; private String tenantId;

View File

@ -29,4 +29,12 @@ public interface RoleService extends IService<RolePo> {
* @date 2022/9/19 下午6:34 * @date 2022/9/19 下午6:34
*/ */
List<RoleVo> findByIds(List<String> ids); List<RoleVo> findByIds(List<String> ids);
/**
* 查询当前租户下所有角色
*
* @return
*/
List<RoleVo> findList();
} }

View File

@ -7,13 +7,16 @@ import cn.zyjblogs.server.role.service.RoleService;
import cn.zyjblogs.server.role.vo.RoleVo; import cn.zyjblogs.server.role.vo.RoleVo;
import cn.zyjblogs.starter.common.entity.context.BaseContext; import cn.zyjblogs.starter.common.entity.context.BaseContext;
import cn.zyjblogs.starter.common.utils.bean.BeanUtils; import cn.zyjblogs.starter.common.utils.bean.BeanUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -55,4 +58,23 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, RolePo> implements
} }
return BeanUtils.map(rolePos, RoleVo.class); return BeanUtils.map(rolePos, RoleVo.class);
} }
/**
* 查询当前租户下所有角色
*
* @param
* @return java.util.List<cn.zyjblogs.server.role.vo.RoleVo>
* @author zhuyijun
* @date 2022/9/22 下午11:32
*/
@Override
public List<RoleVo> findList() {
LambdaQueryWrapper<RolePo> wrapper = Wrappers.lambdaQuery();
wrapper.eq(RolePo::getTenantId, BaseContext.getTenantId());
List<RolePo> rolePos = roleMapper.selectList(wrapper);
if (CollectionUtils.isEmpty(rolePos)) {
return new ArrayList<>();
}
return BeanUtils.map(rolePos, RoleVo.class);
}
} }

View File

@ -1,5 +1,6 @@
package cn.zyjblogs.server.user.controller; package cn.zyjblogs.server.user.controller;
import cn.zyjblogs.server.user.dto.UserDto;
import cn.zyjblogs.server.user.dto.UserPageDto; import cn.zyjblogs.server.user.dto.UserPageDto;
import cn.zyjblogs.server.user.po.UserPo; import cn.zyjblogs.server.user.po.UserPo;
import cn.zyjblogs.server.user.service.UserService; import cn.zyjblogs.server.user.service.UserService;
@ -7,10 +8,15 @@ import cn.zyjblogs.server.user.vo.UserVo;
import cn.zyjblogs.starter.common.entity.response.ResponseObject; import cn.zyjblogs.starter.common.entity.response.ResponseObject;
import cn.zyjblogs.starter.common.entity.response.ResponseResult; import cn.zyjblogs.starter.common.entity.response.ResponseResult;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
@ -21,6 +27,7 @@ import java.util.List;
/** /**
* @author zhuyijun * @author zhuyijun
*/ */
@Api(tags = {"用户管理"})
@RestController @RestController
@RequestMapping("/user") @RequestMapping("/user")
@RequiredArgsConstructor @RequiredArgsConstructor
@ -38,6 +45,7 @@ public class UserController {
* @author zhuyijun * @author zhuyijun
* @date 2022/9/19 上午12:06 * @date 2022/9/19 上午12:06
*/ */
@ApiOperation(value = "", notes = "通过id查询用户")
@GetMapping("/id") @GetMapping("/id")
public ResponseObject<UserPo> findById(@RequestParam String id) { public ResponseObject<UserPo> findById(@RequestParam String id) {
return ResponseResult.success(userService.getById(id)); return ResponseResult.success(userService.getById(id));
@ -50,6 +58,7 @@ public class UserController {
* @author zhuyijun * @author zhuyijun
* @date 2022/9/19 上午1:14 * @date 2022/9/19 上午1:14
*/ */
@ApiOperation(value = "", notes = "分页查询")
@GetMapping("/page") @GetMapping("/page")
public ResponseObject<List<UserVo>> findPage(UserPageDto userPageDto) { public ResponseObject<List<UserVo>> findPage(UserPageDto userPageDto) {
IPage<UserVo> page = userService.findPage(userPageDto); IPage<UserVo> page = userService.findPage(userPageDto);
@ -64,8 +73,15 @@ public class UserController {
* @author zhuyijun * @author zhuyijun
* @date 2022/9/19 上午1:14 * @date 2022/9/19 上午1:14
*/ */
@ApiOperation(value = "", notes = "通过id集合查询用户")
@PostMapping("/findByIds") @PostMapping("/findByIds")
public ResponseObject<List<UserVo>> findByIds(List<String> ids) { public ResponseObject<List<UserVo>> findByIds(List<String> ids) {
return ResponseResult.success(userService.findByIds(ids)); return ResponseResult.success(userService.findByIds(ids));
} }
@ApiOperation(value = "", notes = "用户保存")
@PutMapping("/saveUser")
public ResponseObject<String> saveUser(@RequestBody @Validated UserDto userDto) {
return userService.saveUser(userDto);
}
} }

View File

@ -0,0 +1,72 @@
package cn.zyjblogs.server.user.dto;
import cn.zyjblogs.starter.common.entity.constant.CommonConstant;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import java.time.LocalDateTime;
/**
* @author zhuyijun
*/
@ApiModel(description = "用户Dto")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class UserDto {
private String id;
@NotBlank(message = "账号不能为空")
private String username;
private String name;
private Integer age;
private String avatar;
private String phone;
private String email;
private String inviteUserId;
private Integer status;
private Integer followNum;
private Integer fansNum;
private Integer deleted;
private String description;
private String createUserId;
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JSONField(format = CommonConstant.DATETIME_PATTERN)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = CommonConstant.DATETIME_PATTERN)
private LocalDateTime createTime;
private String editUserId;
@JSONField(format = CommonConstant.DATETIME_PATTERN)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = CommonConstant.DATETIME_PATTERN)
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime editTime;
private String tenantId;
}

View File

@ -1,5 +1,6 @@
package cn.zyjblogs.server.user.mapper; package cn.zyjblogs.server.user.mapper;
import cn.zyjblogs.server.user.dto.UserDto;
import cn.zyjblogs.server.user.dto.UserPageDto; import cn.zyjblogs.server.user.dto.UserPageDto;
import cn.zyjblogs.server.user.po.UserPo; import cn.zyjblogs.server.user.po.UserPo;
import cn.zyjblogs.server.user.vo.UserVo; import cn.zyjblogs.server.user.vo.UserVo;
@ -31,4 +32,12 @@ public interface UserMapper extends BaseMapper<UserPo> {
* @date 2022/9/19 上午12:47 * @date 2022/9/19 上午12:47
*/ */
IPage<UserVo> findPage(IPage<UserPageDto> page, @Param("userPageDto") UserPageDto userPageDto, @Param("tenantId") String tenantId); IPage<UserVo> findPage(IPage<UserPageDto> page, @Param("userPageDto") UserPageDto userPageDto, @Param("tenantId") String tenantId);
/**
* @param userDto
* @return java.lang.Integer
* @author zhuyijun
* @date 2022/9/22 下午6:11
*/
Integer checkUserCount(@Param("userDto") UserDto userDto);
} }

View File

@ -1,12 +1,13 @@
package cn.zyjblogs.server.user.po; package cn.zyjblogs.server.user.po;
import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
@ -14,7 +15,6 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.io.Serializable; import java.io.Serializable;
import java.sql.Timestamp;
import java.time.LocalDateTime; import java.time.LocalDateTime;
/** /**
@ -73,6 +73,7 @@ public class UserPo implements Serializable {
private String createUserId; private String createUserId;
@JsonSerialize(using = LocalDateTimeSerializer.class) @JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@TableField("create_time") @TableField("create_time")
private LocalDateTime createTime; private LocalDateTime createTime;
@ -80,8 +81,8 @@ public class UserPo implements Serializable {
@TableField("edit_user_id") @TableField("edit_user_id")
private String editUserId; private String editUserId;
@JsonSerialize(using = LocalDateTimeSerializer.class) @JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@TableField("edit_time") @TableField("edit_time")
private LocalDateTime editTime; private LocalDateTime editTime;

View File

@ -1,10 +1,13 @@
package cn.zyjblogs.server.user.service; package cn.zyjblogs.server.user.service;
import cn.zyjblogs.server.user.dto.UserDto;
import cn.zyjblogs.server.user.dto.UserPageDto; import cn.zyjblogs.server.user.dto.UserPageDto;
import cn.zyjblogs.server.user.po.UserPo; import cn.zyjblogs.server.user.po.UserPo;
import cn.zyjblogs.server.user.vo.UserVo; import cn.zyjblogs.server.user.vo.UserVo;
import cn.zyjblogs.starter.common.entity.response.ResponseObject;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List; import java.util.List;
@ -30,4 +33,12 @@ public interface UserService extends IService<UserPo> {
*/ */
List<UserVo> findByIds(List<String> ids); List<UserVo> findByIds(List<String> ids);
/**
* @param userDto
* @return java.lang.String
* @author zhuyijun
* @date 2022/9/22 下午5:34
*/
ResponseObject<String> saveUser(@RequestBody UserDto userDto);
} }

View File

@ -1,12 +1,16 @@
package cn.zyjblogs.server.user.service.impl; package cn.zyjblogs.server.user.service.impl;
import cn.zyjblogs.server.user.dto.UserDto;
import cn.zyjblogs.server.user.dto.UserPageDto; import cn.zyjblogs.server.user.dto.UserPageDto;
import cn.zyjblogs.server.user.mapper.UserMapper; import cn.zyjblogs.server.user.mapper.UserMapper;
import cn.zyjblogs.server.user.po.UserPo; import cn.zyjblogs.server.user.po.UserPo;
import cn.zyjblogs.server.user.service.UserService; import cn.zyjblogs.server.user.service.UserService;
import cn.zyjblogs.server.user.vo.UserVo; import cn.zyjblogs.server.user.vo.UserVo;
import cn.zyjblogs.starter.common.entity.context.BaseContext; import cn.zyjblogs.starter.common.entity.context.BaseContext;
import cn.zyjblogs.starter.common.entity.response.HttpCode;
import cn.zyjblogs.starter.common.entity.response.ResponseObject;
import cn.zyjblogs.starter.common.entity.response.ResponseResult;
import cn.zyjblogs.starter.common.utils.bean.BeanUtils; import cn.zyjblogs.starter.common.utils.bean.BeanUtils;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -56,4 +60,33 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, UserPo> implements
} }
return BeanUtils.map(userPos, UserVo.class); return BeanUtils.map(userPos, UserVo.class);
} }
/**
* @param userDto
* @return java.lang.Boolean
* @author zhuyijun
* @date 2022/9/22 下午6:04
*/
@Override
public ResponseObject<String> saveUser(UserDto userDto) {
if (checkUser(userDto)) {
return ResponseResult.error(HttpCode.BAD_REQUEST, "该账号已存在");
}
UserPo userPo = BeanUtils.map(userDto, UserPo.class);
int count = userMapper.insert(userPo);
if (count > 0) {
return ResponseResult.success("用户创建成功");
}
return ResponseResult.error(HttpCode.BAD_REQUEST, "用户创建是失败");
}
/**
* 校验用户是否存在
*
* @param userDto
* @return
*/
public boolean checkUser(UserDto userDto) {
return userMapper.checkUserCount(userDto) > 0;
}
} }

View File

@ -1,7 +1,7 @@
package cn.zyjblogs.server.user.vo; package cn.zyjblogs.server.user.vo;
import cn.zyjblogs.starter.common.entity.constant.CommonConstant;
import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@ -10,7 +10,6 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.io.Serializable; import java.io.Serializable;
import java.sql.Timestamp;
import java.time.LocalDateTime; import java.time.LocalDateTime;
/** /**
@ -51,14 +50,14 @@ public class UserVo implements Serializable {
private String createUserId; private String createUserId;
@JsonSerialize(using = LocalDateTimeSerializer.class) @JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JSONField(format = CommonConstant.DATETIME_PATTERN)
private LocalDateTime createTime; private LocalDateTime createTime;
private String editUserId; private String editUserId;
@JsonSerialize(using = LocalDateTimeSerializer.class) @JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JSONField(format = CommonConstant.DATETIME_PATTERN)
private LocalDateTime editTime; private LocalDateTime editTime;
private String tenantId; private String tenantId;

View File

@ -3,7 +3,10 @@ spring:
active: test active: test
--- ---
spring: spring:
main:
allow-bean-definition-overriding: true
application: application:
name: zyjblogs-rbac name: zyjblogs-rbac
cloud: cloud:
@ -18,6 +21,7 @@ spring:
shared-configs[0]: shared-configs[0]:
data-id: zyjblogs-global-${spring.profiles.active}.yml data-id: zyjblogs-global-${spring.profiles.active}.yml
group: global group: global
refresh: true
discovery: discovery:
server-addr: ${spring.cloud.nacos.config.server-addr} server-addr: ${spring.cloud.nacos.config.server-addr}
username: ${spring.cloud.nacos.config.username} username: ${spring.cloud.nacos.config.username}
@ -33,20 +37,3 @@ security:
client: client:
client-id: ${spring.application.name} client-id: ${spring.application.name}
client-secret: secret client-secret: secret
# 配置了公钥和私钥的位置
rsa:
key:
enable: true
pubKeyPath: public.txt
priKeyPath: private.txt
#security:
# oauth2:
# client:
# client-id: ${spring.application.name}
# client-secret: secret
# access-token-uri: http://localhost:9029/oauth/token
# grant-type: client_credentials
# scope: write read
# authorization:
# check-token-access: http://localhost:9029/oauth/check_token

View File

@ -1,8 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?> <?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"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.zyjblogs.server.user.mapper.UserMapper"> <mapper namespace="cn.zyjblogs.server.user.mapper.UserMapper">
<resultMap id="userMap" type="cn.zyjblogs.server.user.vo.UserVo">
<id column="id" property="id" javaType="java.lang.String"/>
<result column="username" property="username" javaType="java.lang.String"/>
<result column="username" property="username" javaType="java.lang.String"/>
<result column="name" property="name" javaType="java.lang.String"/>
<result column="username" property="username" javaType="java.lang.String"/>
<result column="age" property="age" javaType="java.lang.Integer"/>
<result column="avatar" property="avatar" javaType="java.lang.String"/>
<result column="phone" property="phone" javaType="java.lang.String"/>
<result column="email" property="email" javaType="java.lang.String"/>
<result column="invite_user_id" property="inviteUserId" javaType="java.lang.String"/>
<result column="status" property="status" javaType="java.lang.Integer"/>
<result column="follow_num" property="followNum" javaType="java.lang.Integer"/>
<result column="fans_num" property="fansNum" javaType="java.lang.Integer"/>
<result column="deleted" property="deleted" javaType="java.lang.Integer"/>
<result column="description" property="description" javaType="java.lang.String"/>
<result column="create_user_id" property="createUserId" javaType="java.lang.String"/>
<result column="create_time" property="createTime" javaType="java.sql.Timestamp"/>
<result column="edit_user_id" property="editUserId" javaType="java.lang.String"/>
<result column="edit_time" property="editTime" javaType="java.sql.Timestamp"/>
<result column="tenant_id" property="tenantId" javaType="java.lang.String"/>
</resultMap>
<sql id="base_user_sql">
id,username,name,age,avatar,phone,
email,invite_user_id,status,follow_num,
fans_num,deleted,description,create_user_id,
create_time,edit_user_id,edit_time,tenant_id
</sql>
<select id="findUserByname" resultType="cn.zyjblogs.server.user.po.UserPo"> <select id="findUserByname" resultType="cn.zyjblogs.server.user.po.UserPo">
select * select
<include refid="base_user_sql"/>
from users from users
where deleted = 0 where deleted = 0
and username like CONCAT('%', #{username}, '%') and username like CONCAT('%', #{username}, '%')
@ -11,19 +40,21 @@
</if> </if>
</select> </select>
<select id="findPage" resultType="cn.zyjblogs.server.user.vo.UserVo"> <select id="findPage" resultType="cn.zyjblogs.server.user.vo.UserVo">
select * from users select
<include refid="base_user_sql"/>
from users
where deleted = 0 where deleted = 0
<if test="userPageDto.username != null and userPageDto.username!='' "> <if test="userPageDto.username != null and userPageDto.username!='' ">
and username concat('%',#{userPageDto.username},'%') and username like concat('%',#{userPageDto.username},'%')
</if> </if>
<if test="userPageDto.name != null and userPageDto.name!='' "> <if test="userPageDto.name != null and userPageDto.name!='' ">
and name concat('%',#{name},'%') and name like concat('%',#{name},'%')
</if> </if>
<if test="userPageDto.phone != null and userPageDto.phone!='' "> <if test="userPageDto.phone != null and userPageDto.phone!='' ">
and phone concat('%',#{phone},'%') and phone like concat('%',#{phone},'%')
</if> </if>
<if test="userPageDto.email != null and userPageDto.email!='' "> <if test="userPageDto.email != null and userPageDto.email!='' ">
and email concat('%',#{email},'%') and email like concat('%',#{email},'%')
</if> </if>
<if test="userPageDto.email != null "> <if test="userPageDto.email != null ">
and status = #{userPageDto.status} and status = #{userPageDto.status}
@ -33,5 +64,23 @@
</if> </if>
order by create_time desc order by create_time desc
</select> </select>
<select id="checkUserCount" resultType="java.lang.Integer">
select count(1)
from users
<where>
and deleted = 0 and username = #{userDto.username}
<if test="userDto.name != null and userDto.name!='' ">
or name = #{userDto.name}
</if>
<if test="userDto.phone != null and userDto.phone!='' ">
or phone = #{userDto.phone}
</if>
<if test="userDto.email != null and userDto.email!='' ">
or email = #{userDto.email}
</if>
<if test="userDto.tenantId != null and userDto.tenantId != '' ">
and tenant_id = #{userDto.tenantId}
</if>
</where>
</select>
</mapper> </mapper>

View File

@ -11,19 +11,21 @@
</if> </if>
</select> </select>
<select id="findPage" resultType="cn.zyjblogs.server.user.vo.UserVo"> <select id="findPage" resultType="cn.zyjblogs.server.user.vo.UserVo">
select * from users select
<include refid="base_user_sql"/>
from users
where deleted = 0 where deleted = 0
<if test="userPageDto.username != null and userPageDto.username!='' "> <if test="userPageDto.username != null and userPageDto.username!='' ">
and username concat('%',#{userPageDto.username},'%') and username like concat('%',#{userPageDto.username},'%')
</if> </if>
<if test="userPageDto.name != null and userPageDto.name!='' "> <if test="userPageDto.name != null and userPageDto.name!='' ">
and name concat('%',#{name},'%') and name like concat('%',#{name},'%')
</if> </if>
<if test="userPageDto.phone != null and userPageDto.phone!='' "> <if test="userPageDto.phone != null and userPageDto.phone!='' ">
and phone concat('%',#{phone},'%') and phone like concat('%',#{phone},'%')
</if> </if>
<if test="userPageDto.email != null and userPageDto.email!='' "> <if test="userPageDto.email != null and userPageDto.email!='' ">
and email concat('%',#{email},'%') and email like concat('%',#{email},'%')
</if> </if>
<if test="userPageDto.email != null "> <if test="userPageDto.email != null ">
and status = #{userPageDto.status} and status = #{userPageDto.status}
@ -33,5 +35,23 @@
</if> </if>
order by create_time desc order by create_time desc
</select> </select>
<select id="checkUserCount" resultType="java.lang.Integer">
select count(1)
from users
<where>
and deleted = 0 and username = #{userDto.username}
<if test="userDto.name != null and userDto.name!='' ">
or name = #{userDto.name}
</if>
<if test="userDto.phone != null and userDto.phone!='' ">
or phone = #{userDto.phone}
</if>
<if test="userDto.email != null and userDto.email!='' ">
or email = #{userDto.email}
</if>
<if test="userDto.tenantId != null and userDto.tenantId != '' ">
and tenant_id = #{userDto.tenantId}
</if>
</where>
</select>
</mapper> </mapper>

View File

@ -13,7 +13,7 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@ApiModel( @ApiModel(
description = "状态返回信息" description = "状态返回信息"
) )
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@ -21,30 +21,25 @@ import lombok.NoArgsConstructor;
@Builder @Builder
public class ResponseObject<T> { public class ResponseObject<T> {
@ApiModelProperty( @ApiModelProperty(
value = "响应结果编码", value = "响应结果编码",
example = "200" example = "200"
) )
private int code; private int code;
@ApiModelProperty( @ApiModelProperty(
value = "错误码", value = "响应结果信息",
example = "user_not_exists" example = "请求成功"
)
private String errorCode;
@ApiModelProperty(
value = "响应结果信息",
example = "请求成功"
) )
private String msg; private String msg;
@ApiModelProperty( @ApiModelProperty(
value = "统计列表总数(如果列表存在)", value = "统计列表总数(如果列表存在)",
example = "10" example = "10"
) )
private long count; private long count;
@ApiModelProperty("响应结果数据") @ApiModelProperty("响应结果数据")
private T data; private T data;
@ApiModelProperty( @ApiModelProperty(
value = "当前时间戳", value = "当前时间戳",
example = "1630051102895" example = "1630051102895"
) )
private long timestamp; private long timestamp;
} }

View File

@ -1,6 +1,20 @@
package cn.zyjblogs.starter.common.utils.jwt; package cn.zyjblogs.starter.common.utils.jwt;
import io.jsonwebtoken.*; import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Clock;
import io.jsonwebtoken.CompressionCodec;
import io.jsonwebtoken.CompressionCodecResolver;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Header;
import io.jsonwebtoken.JwsHeader;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.PrematureJwtException;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.SigningKeyResolver;
import io.jsonwebtoken.UnsupportedJwtException;
import io.jsonwebtoken.impl.DefaultClaims; import io.jsonwebtoken.impl.DefaultClaims;
import io.jsonwebtoken.impl.DefaultClock; import io.jsonwebtoken.impl.DefaultClock;
import io.jsonwebtoken.impl.DefaultHeader; import io.jsonwebtoken.impl.DefaultHeader;
@ -21,8 +35,9 @@ import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
/** /**
* jwt解析
*
* @author zhuyijun * @author zhuyijun
*/ */
public class JwtParsers extends DefaultJwtParser { public class JwtParsers extends DefaultJwtParser {

View File

@ -1,25 +1,37 @@
package cn.zyjblogs.starter.common.utils.rsa; package cn.zyjblogs.starter.common.utils.rsa;
import org.slf4j.Logger; import lombok.extern.slf4j.Slf4j;
import org.slf4j.LoggerFactory; import org.apache.commons.io.IOUtils;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import java.io.BufferedReader; import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.*; import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey; import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec; import java.security.spec.X509EncodedKeySpec;
import java.util.Base64; import java.util.Base64;
import java.util.stream.Collectors;
/**
* Copyright (C), 2021, 北京同创永益科技发展有限公司
*
* @author meiji
* @version 3.0.0
* @description RsaUtils
* @date 2021/11/4 9:18
*/
@Slf4j
public final class RsaUtils {
public class RsaUtils {
private static final String DEFAULT_ALGORITHM = "RSA"; private static final String DEFAULT_ALGORITHM = "RSA";
private static final Logger log = LoggerFactory.getLogger(RsaUtils.class);
private RsaUtils() { private RsaUtils() {
} }
@ -86,7 +98,6 @@ public class RsaUtils {
* @param rawStr * @param rawStr
* @param privateKey * @param privateKey
* @return java.lang.String * @return java.lang.String
* @author meiji
* @date 2021/11/4 9:43 * @date 2021/11/4 9:43
*/ */
public static String privateKeyEncrypt(String rawStr, String privateKey) throws Exception { public static String privateKeyEncrypt(String rawStr, String privateKey) throws Exception {
@ -103,7 +114,6 @@ public class RsaUtils {
* @param encodeStr * @param encodeStr
* @param privateKey * @param privateKey
* @return java.lang.String * @return java.lang.String
* @author meiji
* @date 2021/11/4 9:43 * @date 2021/11/4 9:43
*/ */
public static String privateKeyDecrypt(String encodeStr, String privateKey) throws Exception { public static String privateKeyDecrypt(String encodeStr, String privateKey) throws Exception {
@ -119,29 +129,25 @@ public class RsaUtils {
* *
* @param path 公钥路径 * @param path 公钥路径
* @return 公钥 * @return 公钥
* @author tanyuanzhi
* @date 2021/11/9 10:06 * @date 2021/11/9 10:06
*/ */
public static PublicKey getPublicKeyByPath(String path) { public static PublicKey getPublicKeyByPath(String path) {
InputStream inputStream = RsaUtils.class.getClassLoader().getResourceAsStream(path);
if (inputStream == null) {
log.error("获取公钥出错,找不到公钥文件");
return null;
}
String publicKeyStr = new BufferedReader(new InputStreamReader(inputStream)).lines().collect(Collectors.joining());
publicKeyStr = publicKeyStr.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "");
byte[] keyBytes = Base64.getMimeDecoder().decode(publicKeyStr);
// 通过X509编码的Key指令获得公钥对象
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
try { try {
String key = IOUtils.toString(Paths.get(path).toUri(), StandardCharsets.UTF_8);
key = key.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "");
byte[] keyBytes = Base64.getMimeDecoder().decode(key);
// 通过X509编码的Key指令获得公钥对象
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(DEFAULT_ALGORITHM); KeyFactory keyFactory = KeyFactory.getInstance(DEFAULT_ALGORITHM);
PublicKey publicKey = keyFactory.generatePublic(keySpec); PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey; return publicKey;
} catch (Exception e) { } catch (IOException | InvalidKeySpecException e) {
log.error("获取公钥出错", e); log.error("获取公钥出错", e);
return null; return null;
} catch (NoSuchAlgorithmException e) {
log.error("不支持此算法", e);
return null;
} }
} }
} }

View File

@ -1,35 +0,0 @@
package cn.zyjblogs.starter.common.utils.web;
import cn.zyjblogs.starter.common.entity.constant.HttpHeaderConstant;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.HttpServletRequest;
public class RequestUtils {
private RequestUtils() {
}
/**
* 请求是否来自网关
*
* @param request 请求信息
* @return boolean
* @date 2022/3/3 14:19
*/
public static boolean requestFromGateway(HttpServletRequest request) {
return StringUtils.isNotEmpty(request.getHeader(HttpHeaderConstant.REQUEST_FROM_GATEWAY_KEY));
}
/**
* 请求是否来自feign调用
*
* @param request 请求信息
* @return boolean
* @date 2022/3/3 14:19
*/
public static boolean requestFromFeign(HttpServletRequest request) {
return StringUtils.isNotEmpty(request.getHeader(HttpHeaderConstant.REQUEST_FROM_FEIGN_KEY));
}
}

View File

@ -46,6 +46,20 @@
<groupId>org.postgresql</groupId> <groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId> <artifactId>postgresql</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-typehandlers-jsr310</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>

View File

@ -0,0 +1,63 @@
package cn.zyjblogs.starter.mybatisplus.autoconfigure;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* 定义转换器支持的JAVA类型
* 定义转换器支持的数据库类型
*
* @author zhuyijun
*/
@Component
@MappedTypes(LocalDateTime.class)
@MappedJdbcTypes(value = JdbcType.TIMESTAMP, includeNullJdbcType = true)
public class CustomLocalDateTimeTypeHandler extends BaseTypeHandler<LocalDateTime> {
private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
public void setNonNullParameter(PreparedStatement ps, int i, LocalDateTime parameter, JdbcType jdbcType)
throws SQLException {
if (parameter != null) {
ps.setString(i, dateTimeFormatter.format(parameter));
}
}
@Override
public LocalDateTime getNullableResult(ResultSet rs, String columnName) throws SQLException {
String target = rs.getString(columnName);
if (StringUtils.isEmpty(target)) {
return null;
}
return LocalDateTime.parse(target, dateTimeFormatter);
}
@Override
public LocalDateTime getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String target = rs.getString(columnIndex);
if (StringUtils.isEmpty(target)) {
return null;
}
return LocalDateTime.parse(target, dateTimeFormatter);
}
@Override
public LocalDateTime getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String target = cs.getString(columnIndex);
if (StringUtils.isEmpty(target)) {
return null;
}
return LocalDateTime.parse(target, dateTimeFormatter);
}
}

View File

@ -0,0 +1,37 @@
package cn.zyjblogs.starter.mybatisplus.autoconfigure;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.autoconfigure.jdbc.DataSourceHealthContributorAutoConfiguration;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.jdbc.DataSourceHealthIndicator;
import org.springframework.boot.jdbc.metadata.DataSourcePoolMetadataProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import javax.sql.DataSource;
import java.util.Map;
/**
* @author zhuyijun
*/
@Configuration
public class DataSourceHealthConfig extends DataSourceHealthContributorAutoConfiguration {
@Value("${spring.datasource.dbcp2.validation-query:select 1}")
private String defaultQuery;
public DataSourceHealthConfig(Map<String, DataSource> dataSources, ObjectProvider<DataSourcePoolMetadataProvider> metadataProviders) {
super(dataSources, metadataProviders);
}
@Override
protected AbstractHealthIndicator createIndicator(DataSource source) {
DataSourceHealthIndicator indicator = (DataSourceHealthIndicator) super.createIndicator(source);
if (!StringUtils.hasText(indicator.getQuery())) {
indicator.setQuery(defaultQuery);
}
return indicator;
}
}

View File

@ -1,2 +1,4 @@
org.springframework.boot.cn.zyjblogs.starter.feign.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.cn.zyjblogs.starter.feign.autoconfigure.EnableAutoConfiguration=\
cn.zyjblogs.starter.mybatisplus.autoconfigure.MyBatisPlusConfig cn.zyjblogs.starter.mybatisplus.autoconfigure.MyBatisPlusConfig,\
cn.zyjblogs.starter.mybatisplus.autoconfigure.DataSourceHealthConfig,\
cn.zyjblogs.starter.mybatisplus.autoconfigure.CustomLocalDateTimeTypeHandler

View File

@ -7,6 +7,6 @@ import org.springframework.context.annotation.Configuration;
* @author zhuyijun * @author zhuyijun
*/ */
@Configuration @Configuration
@EnableConfigurationProperties(RsaKeyProperties.class) @EnableConfigurationProperties({RsaKeyProperties.class, WhiteListProperties.class})
public class OauthAutoConfiguration { public class OauthAutoConfiguration {
} }

View File

@ -4,6 +4,7 @@ package cn.zyjblogs.starter.oauth.autoconfigure;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
/** /**
* rsa 路径配置文件 * rsa 路径配置文件
@ -13,6 +14,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
@Getter @Getter
@Setter @Setter
@ConfigurationProperties(prefix = "rsa.key") @ConfigurationProperties(prefix = "rsa.key")
@RefreshScope
public class RsaKeyProperties { public class RsaKeyProperties {
/** /**
* 启用rsa对token进行加密 * 启用rsa对token进行加密

View File

@ -0,0 +1,20 @@
package cn.zyjblogs.starter.oauth.autoconfigure;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import java.util.List;
/**
* 白名单
*
* @author zhuyijun
*/
@Data
@RefreshScope
@ConfigurationProperties(prefix = "zyjblogs.whilelist")
public class WhiteListProperties {
private List<String> allowPaths;
}

View File

@ -1,4 +1,4 @@
package cn.zyjblogs.starter.oauth.config; package cn.zyjblogs.starter.oauth.interceptor;
import cn.zyjblogs.starter.common.entity.constant.HttpHeaderConstant; import cn.zyjblogs.starter.common.entity.constant.HttpHeaderConstant;
import cn.zyjblogs.starter.common.entity.context.BaseContext; import cn.zyjblogs.starter.common.entity.context.BaseContext;
@ -10,10 +10,13 @@ import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
/**
* @author zhuyijun
*/
@Slf4j @Slf4j
public class JwtTokenHandlerInterceptor extends HandlerInterceptorAdapter { public class JwtTokenHandlerInterceptor extends HandlerInterceptorAdapter {
private boolean checkInner; private final boolean checkInner;
public JwtTokenHandlerInterceptor(boolean checkInner) { public JwtTokenHandlerInterceptor(boolean checkInner) {
this.checkInner = checkInner; this.checkInner = checkInner;
@ -22,6 +25,9 @@ public class JwtTokenHandlerInterceptor extends HandlerInterceptorAdapter {
@Override @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String authorization = request.getHeader(HttpHeaderConstant.AUTHORIZATION); String authorization = request.getHeader(HttpHeaderConstant.AUTHORIZATION);
if (!checkInner) {
return true;
}
//token为空直接放行 //token为空直接放行
if (StringUtils.isEmpty(authorization)) { if (StringUtils.isEmpty(authorization)) {
BaseContext.set(ContextDto.builder().build()); BaseContext.set(ContextDto.builder().build());

View File

@ -1,4 +1,4 @@
package cn.zyjblogs.starter.oauth.config; package cn.zyjblogs.starter.oauth.interceptor;
import cn.zyjblogs.starter.common.entity.constant.HttpHeaderConstant; import cn.zyjblogs.starter.common.entity.constant.HttpHeaderConstant;
import cn.zyjblogs.starter.common.entity.context.BaseContext; import cn.zyjblogs.starter.common.entity.context.BaseContext;
@ -29,12 +29,13 @@ public class OauthFeignInterceptorAutoConfiguration {
/** /**
* token信息补全,token不能为空 * token信息补全,token不能为空
*
* @return 补全后得token
* @author liuweicheng * @author liuweicheng
* @date 2022/03/12 * @date 2022/03/12
* @return 补全后得token
*/ */
private String tokenCompletion(String token){ private String tokenCompletion(String token) {
if(token.indexOf(HttpHeaderConstant.AUTHORIZATION_TYPE) != 0){ if (token.indexOf(HttpHeaderConstant.AUTHORIZATION_TYPE) != 0) {
token = HttpHeaderConstant.AUTHORIZATION_TYPE + " " + token; token = HttpHeaderConstant.AUTHORIZATION_TYPE + " " + token;
} }
return token; return token;

View File

@ -1,4 +1,4 @@
package cn.zyjblogs.starter.oauth.config; package cn.zyjblogs.starter.oauth.interceptor;
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;

View File

@ -1,5 +1,6 @@
package cn.zyjblogs.starter.oauth.resource; package cn.zyjblogs.starter.oauth.resource;
import cn.zyjblogs.starter.oauth.autoconfigure.WhiteListProperties;
import cn.zyjblogs.starter.oauth.handler.ResourceAccessDeniedHandler; import cn.zyjblogs.starter.oauth.handler.ResourceAccessDeniedHandler;
import cn.zyjblogs.starter.oauth.handler.ResourceAuthenticationEntryPoint; import cn.zyjblogs.starter.oauth.handler.ResourceAuthenticationEntryPoint;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -26,6 +27,7 @@ public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Value("${spring.application.name}") @Value("${spring.application.name}")
private String resourceId; private String resourceId;
private final TokenStore tokenStore; private final TokenStore tokenStore;
private final WhiteListProperties whiteListProperties;
@Override @Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception { public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
@ -41,6 +43,7 @@ public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
public void configure(HttpSecurity http) throws Exception { public void configure(HttpSecurity http) throws Exception {
http.csrf().disable() http.csrf().disable()
.authorizeRequests() .authorizeRequests()
.antMatchers("/webjars/**", "/swagger-ui.html/**", "/swagger-resources/**", "/v2/api-docs/**", String.join(",", whiteListProperties.getAllowPaths())).permitAll()
.anyRequest() .anyRequest()
.authenticated() .authenticated()
.and() .and()

View File

@ -1,4 +1,4 @@
package cn.zyjblogs.starter.oauth.security; package cn.zyjblogs.starter.oauth.token;
import cn.zyjblogs.starter.common.entity.constant.ContextKeyConstant; import cn.zyjblogs.starter.common.entity.constant.ContextKeyConstant;
import cn.zyjblogs.starter.common.entity.context.BaseContext; import cn.zyjblogs.starter.common.entity.context.BaseContext;

View File

@ -1,10 +1,12 @@
package cn.zyjblogs.starter.oauth.security; package cn.zyjblogs.starter.oauth.token;
import cn.zyjblogs.starter.oauth.autoconfigure.RsaKeyProperties; import cn.zyjblogs.starter.oauth.autoconfigure.RsaKeyProperties;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
@ -23,6 +25,11 @@ public class TokenConfig {
private final RsaKeyProperties rsaKeyProperties; private final RsaKeyProperties rsaKeyProperties;
private final OauthAccessTokenConverter oauthAccessTokenConverter; private final OauthAccessTokenConverter oauthAccessTokenConverter;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/** /**
* 令牌存储策略 * 令牌存储策略
* *

View File

@ -1,7 +1,7 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.zyjblogs.starter.oauth.config.OauthFeignInterceptorAutoConfiguration,\ cn.zyjblogs.starter.oauth.interceptor.OauthFeignInterceptorAutoConfiguration,\
cn.zyjblogs.starter.oauth.resource.ResourceServerConfig,\ cn.zyjblogs.starter.oauth.resource.ResourceServerConfig,\
cn.zyjblogs.starter.oauth.security.TokenConfig,\ cn.zyjblogs.starter.oauth.token.TokenConfig,\
cn.zyjblogs.starter.oauth.security.OauthAccessTokenConverter,\ cn.zyjblogs.starter.oauth.token.OauthAccessTokenConverter,\
cn.zyjblogs.starter.oauth.config.OauthInterceptorAutoConfiguration,\ cn.zyjblogs.starter.oauth.interceptor.OauthInterceptorAutoConfiguration,\
cn.zyjblogs.starter.oauth.autoconfigure.OauthAutoConfiguration cn.zyjblogs.starter.oauth.autoconfigure.OauthAutoConfiguration

View File

@ -45,6 +45,12 @@
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId> <artifactId>spring-jdbc</artifactId>
</dependency> </dependency>
<!-- Spring 集成 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>

View File

@ -0,0 +1,145 @@
package cn.zyjblogs.starter.web.autoconfig;
import com.google.common.collect.Lists;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.Contact;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.service.SecurityScheme;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
@EnableOpenApi
@Configuration
@Import(BeanValidatorPluginsConfiguration.class)
public class Knife4jAutoConfigurationConfig {
@Value("${spring.application.name}")
private String applicationName;
// @Bean
// public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
// return new BeanPostProcessor() {
//
// @Override
// public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
// customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
// }
// return bean;
// }
//
// private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
// List<T> copy = mappings.stream()
// .filter(mapping -> mapping.getPatternParser() == null)
// .collect(Collectors.toList());
// mappings.clear();
// mappings.addAll(copy);
// }
//
// @SuppressWarnings("unchecked")
// private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
// try {
// Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
// field.setAccessible(true);
// return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
// } catch (IllegalArgumentException | IllegalAccessException e) {
// throw new IllegalStateException(e);
// }
// }
// };
// }
@Bean(value = "defaultApi")
public Docket defaultApi() {
return new Docket(DocumentationType.SWAGGER_2)
.directModelSubstitute(LocalDateTime.class, Date.class)
.directModelSubstitute(LocalDate.class, String.class)
.directModelSubstitute(LocalTime.class, String.class)
.directModelSubstitute(ZonedDateTime.class, String.class)
.apiInfo(apiInfo())
.select()
//controller层包路径
.apis(RequestHandlerSelectors.basePackage("cn.zyjblogs.server"))
.paths(PathSelectors.any())
.build()
.securityContexts(Lists.newArrayList(securityContext(), securityContext())).securitySchemes(Lists.<SecurityScheme>newArrayList(apiKey()));
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(applicationName.toUpperCase() + " RESTFUL APIS")
.contact(new Contact("zyjblogs", "", ""))
.version("1.0.0")
.build();
}
/**
* token头key
*
* @param
* @return ApiKey
* @author liuweicheng
* @date 2021/11/4 11:29
*/
private ApiKey apiKey() {
return new ApiKey("BearerToken", "Authorization", "header");
}
/**
* token定义
*
* @param
* @return SecurityContext
* @author liuweicheng
* @date 2021/11/4 11:28
*/
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex("/.*"))
.build();
}
/**
* token描述定义
*
* @param
* @return java.util.List<springfox.documentation.service.SecurityReference>
* @author zhuyijun
* @date 2022/9/23 上午12:20
*/
private List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return Lists.newArrayList(new SecurityReference("BearerToken", authorizationScopes));
}
}

View File

@ -1,3 +1,4 @@
## Auto Configure ## Auto Configure
org.springframework.boot.cn.zyjblogs.starter.feign.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.cn.zyjblogs.starter.feign.autoconfigure.EnableAutoConfiguration=\
cn.zyjblogs.starter.web.autoconfig.GlobalExceptionHandlerAutoConfiguration cn.zyjblogs.starter.web.autoconfig.GlobalExceptionHandlerAutoConfiguration,\
cn.zyjblogs.starter.web.autoconfig.Knife4jAutoConfigurationConfig