OCT 1. SpringSecurity 增加认证拦截

This commit is contained in:
黄昕 2023-12-14 15:40:01 +08:00
parent 68fc180711
commit ea53882c71
30 changed files with 765 additions and 45 deletions

View File

@ -30,7 +30,7 @@ spring.datasource.dbcp2.connection-properties=characterEncoding=utf8
mybatis.mapper-locations=classpath*:mappers/*.xml
mybatis.type-aliases-package=com.cmhi.gds.pojo.entry
mybatis.configuration.default-enum-type-handler=com.cmhi.cf.common.CommonEnumHandler
mybatis-plus.global-config.banner = false
mybatis-flex.global-config.print-banner = false
#pagehelper
pagehelper.helper-dialect=mysql
@ -45,3 +45,8 @@ log4j.logger.org.mybatis=info
# swagger-ui custom path
springdoc.swagger-ui.path=/swagger-ui.html
# JWT configure
jwt.http-head=Authorization
jwt.secret-key=MTIzNDU2Nzg=
jwt.expire-time=604800

View File

@ -86,6 +86,11 @@
<appender-ref ref="DATA"/>
</logger>
<logger name="org.springframework.security" level="trace" additivity="false">
<appender-ref ref="DATA"/>
<appender-ref ref="CONSOLE"/>
</logger>
<root level="${LOG_LEVEL}">
<appender-ref ref="SYSTEM-LOG-FILE"/>
<appender-ref ref="CONSOLE"/>

73
pom.xml
View File

@ -39,11 +39,6 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
@ -60,12 +55,6 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
@ -117,6 +106,46 @@
<artifactId>commons-io</artifactId>
<version>2.15.1</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.baomidou</groupId>-->
<!-- <artifactId>mybatis-plus-boot-starter</artifactId>-->
<!-- <version>3.5.3.2</version>-->
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <groupId>org.mybatis</groupId>-->
<!-- <artifactId>mybatis-spring</artifactId>-->
<!-- </exclusion>-->
<!-- </exclusions>-->
<!-- </dependency>-->
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.7.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.12.3</version>
</dependency>
</dependencies>
<build>
@ -154,6 +183,28 @@
<exclude>templates/**</exclude>
<exclude>static/**</exclude>
</excludes>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${lombok-mapstruct-binding.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
<path>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>${mybatis-flex.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>

View File

@ -0,0 +1,28 @@
package com.cmhi.cf.authentication.configure;
import jakarta.annotation.PostConstruct;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.Optional;
@Configuration
@ConfigurationProperties(prefix = "jwt")
@Slf4j
@Data
public class JwtConfigure {
private String secretKey;
private Long expireTime;
private String httpHead;
@PostConstruct
private void initGlobalValue() {
log.info("Current: secretKey = {}, httpHead = {}, expireTime = {}", secretKey, httpHead, expireTime);
secretKey = Optional.ofNullable(secretKey).orElse("");
httpHead = Optional.ofNullable(httpHead).orElse("Authorization");
expireTime = Optional.ofNullable(expireTime).orElse((long) (7 * 24 * 3600));
}
}

View File

@ -1,6 +1,5 @@
package com.cmhi.cf.authentication.configure;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
@ -8,6 +7,8 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
@ -18,7 +19,6 @@ import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
@MapperScan(value = {"com.cmhi.cf.authentication.db.mapper"})
public class SecuritySecurity {
@Bean
public static PasswordEncoder passwordEncoder() {
@ -30,11 +30,13 @@ public class SecuritySecurity {
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(resp -> {
resp.requestMatchers(HttpMethod.POST, "/version").permitAll();
resp.requestMatchers(HttpMethod.GET, "/swagger-ui/**", "/v3/api-docs/**", "/swagger-ui.html").permitAll();
resp.requestMatchers(HttpMethod.GET, "/version").hasRole("USER");
}).formLogin(AbstractAuthenticationFilterConfigurer::permitAll);
resp.requestMatchers(HttpMethod.POST, "/version").permitAll();
resp.requestMatchers(HttpMethod.GET, "/swagger-ui/**", "/v3/api-docs/**", "/swagger-ui.html").permitAll();
resp.requestMatchers(HttpMethod.GET, "/version").hasRole("USER");
resp.anyRequest().authenticated();
}).formLogin(AbstractAuthenticationFilterConfigurer::permitAll)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))//禁用session因为我们已经使用了JWT
.logout(AbstractHttpConfigurer::disable);
//(form -> form.loginPage("/login").defaultSuccessUrl("/index").permitAll()).logout(LogoutConfigurer::permitAll);
return http.build();

View File

@ -0,0 +1,26 @@
package com.cmhi.cf.authentication.exception;
import com.cmhi.cf.common.ErrorCode;
import lombok.Getter;
import lombok.Setter;
import org.springframework.security.core.AuthenticationException;
@Getter
@Setter
public class CommonAuthException extends AuthenticationException {
private ErrorCode err;
private String description;
public CommonAuthException(ErrorCode err) {
super(err.getDescription());
this.err = err;
this.description = err.getDescription();
}
public CommonAuthException(ErrorCode err, String readme) {
super(readme);
this.err = err;
this.description = readme;
}
}

View File

@ -0,0 +1,21 @@
package com.cmhi.cf.authentication.exception;
import com.cmhi.cf.common.ErrorCode;
public class JwtTokenException extends RuntimeException {
private ErrorCode err;
private String description;
public JwtTokenException(ErrorCode err) {
super(err.getDescription());
this.err = err;
this.description = err.getDescription();
}
public JwtTokenException(ErrorCode err, String readme) {
super(readme);
this.err = err;
this.description = readme;
}
}

View File

@ -0,0 +1,31 @@
package com.cmhi.cf.authentication.impl;
import com.cmhi.cf.authentication.exception.CommonAuthException;
import com.cmhi.cf.common.ErrorCode;
import com.cmhi.cf.misc.HelperUtils;
import com.cmhi.cf.restapi.pojo.vo.ProtocolRespDTO;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class LoginFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {
response.setContentType("application/json;charset=UTF-8");
ServletOutputStream outputStream = response.getOutputStream();
if (exception instanceof CommonAuthException e) {
outputStream.write(HelperUtils.getJsonBytes(ProtocolRespDTO.result(e.getErr())));
} else {
outputStream.write(HelperUtils.getJsonBytes(ProtocolRespDTO.result(ErrorCode.ERR_PARAMS)));
}
outputStream.flush();
outputStream.close();
}
}

View File

@ -0,0 +1,53 @@
package com.cmhi.cf.authentication.impl;
import com.cmhi.cf.authentication.misc.JwtUtils;
import com.cmhi.cf.common.ErrorCode;
import com.cmhi.cf.database.authentication.entity.UserCredential;
import com.cmhi.cf.database.authentication.service.UserCredentialService;
import com.cmhi.cf.misc.HelperUtils;
import com.cmhi.cf.restapi.pojo.vo.ProtocolRespDTO;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import static com.cmhi.cf.database.authentication.entity.table.UserCredentialTableDef.USER_CREDENTIAL;
@Component
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
@Resource
private JwtUtils jwtUtils;
@Resource
private UserCredentialService userCredentialService;
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
ServletOutputStream outputStream = response.getOutputStream();
response.setContentType("application/json;charset=UTF-8");
QueryWrapper wrapper = QueryWrapper.create()
.select()
.where(USER_CREDENTIAL.IDENTIFIER.eq(authentication.getName()));
UserCredential uc = userCredentialService.getOne(wrapper);
if (uc == null) {
outputStream.write(HelperUtils.getJsonBytes(ProtocolRespDTO.result(ErrorCode.ERR_USERNOTFOUND), StandardCharsets.UTF_8));
} else {
// 生成JWT并放置到请求头中
String jwt = jwtUtils.getToken(uc.getUserId());
response.setHeader(jwtUtils.getHeadValue(), jwt);
outputStream.write(HelperUtils.getJsonBytes(ProtocolRespDTO.result(ErrorCode.ERR_OK)));
}
outputStream.flush();
outputStream.close();
}
}

View File

@ -0,0 +1,117 @@
package com.cmhi.cf.authentication.misc;
import com.cmhi.cf.authentication.configure.JwtConfigure;
import com.cmhi.cf.authentication.exception.JwtTokenException;
import com.cmhi.cf.common.ErrorCode;
import com.cmhi.cf.crypto.arithmetic.CryptoHelper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import io.micrometer.common.util.StringUtils;
import jakarta.annotation.Resource;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
@Data
@Component
@Slf4j
public class JwtUtils {
@Resource
private JwtConfigure jwtConfigure;
public String getHeadValue() {
return jwtConfigure.getHttpHead();
}
public String getToken(Long userId) {
Date nowDate = new Date();
Date expireDate = new Date(nowDate.getTime() + 1000 * jwtConfigure.getExpireTime());
//Map<String, Object> claims = new HashMap<String, Object>();
//User user = new User();
//user.setId(1000L);
//user.setName("张三");
//claims.put(KEY_CLAIMS, user);
return Jwts.builder()
.header()
.add("typ", "JWT")
//.add(claims)
.and()
.signWith(Keys.hmacShaKeyFor(getSecretKey(jwtConfigure.getSecretKey())))
.expiration(expireDate)
.issuedAt(nowDate)
.id(userId.toString())
.compact();
}
// public User parseToken(String token) throws ParseException {
//
// String msg = null;
// try {
// Jws<Claims> jws = Jwts.parser().setSigningKey(getSecretKey()).requireSubject(SUBJECT)//校验必须有这个属性可以省略这步
// .parseClaimsJws(token);
//
// Claims claims = jws.getBody();//Claims是一个Map
//
// log.info("claims===" + JSONUtil.toJsonStr(claims));
// log.info("claims.getIssuedAt()===" + claims.getIssuedAt());
// log.info("claims.getExpiration()===" + claims.getExpiration());
//
// //map转实体
// User user = BeanUtil.toBean(claims.get(KEY_CLAIMS), User.class);
// log.info("user===" + JSONUtil.toJsonStr(user));
//
// return user;
//
//
// } catch (SignatureException se) {
// msg = "密钥错误";
// log.error(msg, se);
// throw new RunException(msg);
//
// } catch (MalformedJwtException me) {
// msg = "密钥算法或者密钥转换错误";
// log.error(msg, me);
// throw new RunException(msg);
//
// } catch (MissingClaimException mce) {
// msg = "密钥缺少校验数据";
// log.error(msg, mce);
// throw new RunException(msg);
//
// } catch (ExpiredJwtException mce) {
// msg = "密钥已过期";
// log.error(msg, mce);
// throw new RunException(msg);
//
// } catch (JwtException jwte) {
// msg = "密钥解析错误";
// log.error(msg, jwte);
// throw new RunException(msg);
// }
//
// }
private byte[] getSecretKey(String base64Key) {
if (StringUtils.isBlank(base64Key)) {
throw new JwtTokenException(ErrorCode.ERR_TOKEN_KEY, ErrorCode.ERR_TOKEN_KEY.getDescription());
}
try {
return CryptoHelper.sha256Encryption(base64Key);
} catch (NoSuchAlgorithmException e) {
throw new JwtTokenException(ErrorCode.ERR_TOKEN_KEY, ErrorCode.ERR_TOKEN_KEY.getDescription());
}
}
// 判断JWT是否过期
public boolean isTokenExpired(Claims claims) {
return claims.getExpiration().before(new Date());
}
}

View File

@ -54,6 +54,8 @@ public enum ErrorCode implements BaseEnum {
ERR_ENCRYPT_AES256(110, "AES256加密失败"),
ERR_DECRYPT_AES256(111, "AES256解密失败"),
ERR_CRYPTO_KEY(112, "错误的秘钥"),
ERR_TOKEN_KEY(113, "Token 秘钥错误")
;
private final int errno;

View File

@ -32,6 +32,7 @@ public class CommonFrameworkApi {
@GetMapping("/version")
@ResponseBody
public ProtocolRespDTO<? extends BaseRespStatus> getVersionV2() {
log.info("Request: {}", System.currentTimeMillis());
return ProtocolRespDTO.result(ErrorCode.ERR_OK);
}
}

View File

@ -0,0 +1,59 @@
package com.cmhi.cf.database.authentication.entity;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 用户表(User)表实体类
*
* @author makejava
* @since 2023-12-13 16:49:44
*/
@Data
@Schema(name = "UserDO", description = "用户表")
@Table("user")
public class User {
/**
* id
*/
@Schema(description = "id")
@Id(keyType = KeyType.Auto)
private Long id;
/**
* 创建时间
*/
@Schema(description = "创建时间")
@Column(value = "created_time")
private Object createdTime;
/**
* 创建用户
*/
@Schema(description = "创建用户")
@Column(value = "gender")
private Integer gender;
/**
* 当前状态: 0 --> 正常 1 --> 删除
*/
@Schema(description = "当前状态: 0 --> 正常, 1 --> 删除")
@Column(value = "state")
private Integer state;
/**
* 用户名
*/
@Schema(description = "用户名")
@Column(value = "username")
private String username;
/**
* 组织架构id
*/
@Schema(description = "组织架构id")
@Column(value = "organization_id")
private Long organizationId;
}

View File

@ -0,0 +1,53 @@
package com.cmhi.cf.database.authentication.entity;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 用户认证(UserCredential)表实体类
*
* @author makejava
* @since 2023-12-13 16:49:44
*/
@Data
@Schema(name = "UserCredentialDO", description = "用户认证")
@Table("user_credential")
public class UserCredential {
/**
* id
*/
@Schema(description = "id")
@Id(keyType = KeyType.Auto)
private Long id;
/**
* 用户密码
*/
@Schema(description = "用户密码")
@Column(value = "credential")
private String credential;
/**
* 用户标识
*/
@Schema(description = "用户标识")
@Column(value = "identifier")
private String identifier;
/**
* 登录类型
*/
@Schema(description = "登录类型")
@Column(value = "identity_type")
private Integer identityType;
/**
* 用户id
*/
@Schema(description = "用户id")
@Column(value = "user_id")
private Long userId;
}

View File

@ -0,0 +1,27 @@
package com.cmhi.cf.database.authentication.mapper;
import com.cmhi.cf.database.authentication.entity.UserCredential;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 用户认证(UserCredential)表数据库访问层
*
* @author makejava
* @since 2023-12-13 16:49:44
*/
public interface UserCredentialMapper extends BaseMapper<UserCredential> {
/**
* 批量新增或按主键更新数据MyBatis原生foreach方法
*
* @param entities List<UserCredentialDO> 实例对象列表
* @return 影响行数
* @throws org.springframework.jdbc.BadSqlGrammarException 入参是空List的时候会抛SQL语句错误的异常请自行校验入参
*/
int insertOrUpdateBatch(@Param("entities") List<UserCredential> entities);
}

View File

@ -0,0 +1,27 @@
package com.cmhi.cf.database.authentication.mapper;
import com.cmhi.cf.database.authentication.entity.User;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 用户表(User)表数据库访问层
*
* @author makejava
* @since 2023-12-13 16:49:44
*/
public interface UserMapper extends BaseMapper<User> {
/**
* 批量新增或按主键更新数据MyBatis原生foreach方法
*
* @param entities List<UserDO> 实例对象列表
* @return 影响行数
* @throws org.springframework.jdbc.BadSqlGrammarException 入参是空List的时候会抛SQL语句错误的异常请自行校验入参
*/
int insertOrUpdateBatch(@Param("entities") List<User> entities);
}

View File

@ -0,0 +1,15 @@
package com.cmhi.cf.database.authentication.service;
import com.cmhi.cf.database.authentication.entity.UserCredential;
import com.mybatisflex.core.service.IService;
/**
* 用户认证(UserCredential)表服务接口
*
* @author makejava
* @since 2023-12-13 16:49:44
*/
public interface UserCredentialService extends IService<UserCredential> {
}

View File

@ -0,0 +1,15 @@
package com.cmhi.cf.database.authentication.service;
import com.cmhi.cf.database.authentication.entity.User;
import com.mybatisflex.core.service.IService;
/**
* 用户表(User)表服务接口
*
* @author makejava
* @since 2023-12-13 16:49:44
*/
public interface UserService extends IService<User> {
}

View File

@ -0,0 +1,19 @@
package com.cmhi.cf.database.authentication.service.impl;
import com.cmhi.cf.database.authentication.mapper.UserCredentialMapper;
import com.cmhi.cf.database.authentication.service.UserCredentialService;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.cmhi.cf.database.authentication.entity.UserCredential;
import org.springframework.stereotype.Service;
/**
* 用户认证(UserCredential)表服务实现类
*
* @author makejava
* @since 2023-12-13 16:49:44
*/
@Service("userCredentialService")
public class UserCredentialServiceImpl extends ServiceImpl<UserCredentialMapper, UserCredential> implements UserCredentialService {
}

View File

@ -0,0 +1,19 @@
package com.cmhi.cf.database.authentication.service.impl;
import com.cmhi.cf.database.authentication.entity.User;
import com.cmhi.cf.database.authentication.mapper.UserMapper;
import com.cmhi.cf.database.authentication.service.UserService;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* 用户表(User)表服务实现类
*
* @author makejava
* @since 2023-12-13 16:49:44
*/
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

View File

@ -0,0 +1,9 @@
package com.cmhi.cf.database.config;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan(value = {"com.cmhi.cf.database.common.mapper", "com.cmhi.cf.database.authentication.mapper"})
public class MybatisFlexConfigure {
}

View File

@ -1,19 +0,0 @@
package com.cmhi.cf.database.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.cmhi.cf.database.mapper")
public class MybatisPlusConfigure {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
// 添加分页插件
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}

View File

@ -1,16 +1,22 @@
package com.cmhi.cf.misc;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class HelperUtils {
private static final ObjectMapper objMapper = new ObjectMapper();
public static String bytesToHexString(byte[] bArray) {
StringBuilder sb = new StringBuilder(bArray.length);
String sTemp;
@ -76,4 +82,20 @@ public class HelperUtils {
// private HelperUtils() {
// throw new UnsupportedOperationException();
// }
public static <T> String getJson(T obj) throws JsonProcessingException {
return objMapper.writeValueAsString(obj);
}
public static <T> byte[] getJsonBytes(T obj, Charset charset) throws JsonProcessingException {
return objMapper.writeValueAsString(obj).getBytes(charset);
}
public static <T> byte[] getJsonBytes(T obj) throws JsonProcessingException {
return objMapper.writeValueAsString(obj).getBytes(StandardCharsets.UTF_8);
}
public static <T> Object jsonGetObject(String json, Class<T> valueType) throws JsonProcessingException {
return objMapper.readValue(json, valueType);
}
}

View File

@ -1,5 +1,6 @@
package com.cmhi.cf.restapi.interceptor;
import com.cmhi.cf.misc.HelperUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
@ -18,7 +19,7 @@ import java.nio.charset.StandardCharsets;
@Getter
@Slf4j
public class RequestBodyCacheWrapper extends HttpServletRequestWrapper {
private final String body;
private String body;
public RequestBodyCacheWrapper(HttpServletRequest request) throws IOException {
super(request);
@ -43,9 +44,13 @@ public class RequestBodyCacheWrapper extends HttpServletRequestWrapper {
}
}
ObjectMapper mapper = new ObjectMapper();
Object obj = mapper.readValue(stringBuilder.toString(), Object.class);
body = new ObjectMapper().writeValueAsString(obj);
try {
Object obj = HelperUtils.jsonGetObject(stringBuilder.toString(), Object.class);
body = HelperUtils.getJson(obj);
} catch (Exception e) {
body = "";
}
}
@Override

View File

@ -20,8 +20,6 @@ import lombok.extern.slf4j.Slf4j;
@AllArgsConstructor
@JsonPropertyOrder({"ver", "cryptoType", "timeStamp", "code", "msgContent"})
public class ProtocolRespDTO<T> extends BaseProtocolDTO<T> {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private Integer code;
private static <T> ProtocolRespDTO<T> result(ErrorCode err, Integer httpCode, T respMsg) {

View File

@ -3,6 +3,7 @@ package com.cmhi.cf.restapi.service.impl;
import com.cmhi.cf.common.ErrorCode;
import com.cmhi.cf.configure.ConstValue;
import com.cmhi.cf.crypto.arithmetic.CryptoHelper;
import com.cmhi.cf.misc.HelperUtils;
import com.cmhi.cf.restapi.config.ProtoCryptoType;
import com.cmhi.cf.restapi.config.ProtocolConfigure;
import com.cmhi.cf.restapi.crypto.DecryptRequestProtocol;
@ -152,7 +153,7 @@ public class ProtocolSecurityServiceImpl implements ProtocolSecurityService {
try {
Method getMsgMethod = orgProtocol.getClass().getMethod("getMsgContent");
Method getCode = orgProtocol.getClass().getMethod("getCode");
msgContentJsonString = new ObjectMapper().writeValueAsString(getMsgMethod.invoke(orgProtocol));
msgContentJsonString = HelperUtils.getJson(getMsgMethod.invoke(orgProtocol));
cryptoObject.setCode((Integer) getCode.invoke(orgProtocol));
} catch (Exception e) {
log.error("Json encode message error: {}", orgProtocol);

View File

@ -0,0 +1,37 @@
<?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.cmhi.cf.database.authentication.mapper.UserCredentialMapper">
<resultMap id="BaseResultMap" type="com.cmhi.cf.database.authentication.entity.UserCredential">
<!--@Table user_credential-->
<result property="id" column="id" jdbcType="INTEGER"/>
<result property="credential" column="credential" jdbcType="VARCHAR"/>
<result property="identifier" column="identifier" jdbcType="VARCHAR"/>
<result property="identityType" column="identity_type" jdbcType="INTEGER"/>
<result property="userId" column="user_id" jdbcType="INTEGER"/>
</resultMap>
<sql id="Base_Column_List">
id,
credential,
identifier,
identity_type,
user_id
</sql>
<!-- 批量插入或按主键更新 -->
<insert id="insertOrUpdateBatch" keyProperty="id" useGeneratedKeys="true">
insert into rbac.user_credential(credential, identifier, identity_type, user_id)
values
<foreach collection="entities" item="entity" separator=",">
(#{entity.credential}, #{entity.identifier}, #{entity.identityType}, #{entity.userId})
</foreach>
on duplicate key update
credential = values(credential) , identifier = values(identifier) , identity_type = values(identity_type) ,
user_id = values(user_id)
</insert>
</mapper>

View File

@ -0,0 +1,39 @@
<?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.cmhi.cf.database.authentication.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.cmhi.cf.database.authentication.entity.User">
<!--@Table user-->
<result property="id" column="id" jdbcType="INTEGER"/>
<result property="createdTime" column="created_time" jdbcType="VARCHAR"/>
<result property="gender" column="gender" jdbcType="INTEGER"/>
<result property="state" column="state" jdbcType="INTEGER"/>
<result property="username" column="username" jdbcType="VARCHAR"/>
<result property="organizationId" column="organization_id" jdbcType="INTEGER"/>
</resultMap>
<sql id="Base_Column_List">
id,
created_time,
gender,
state,
username,
organization_id
</sql>
<!-- 批量插入或按主键更新 -->
<insert id="insertOrUpdateBatch" keyProperty="id" useGeneratedKeys="true">
insert into rbac.user(created_time, gender, state, username, organization_id)
values
<foreach collection="entities" item="entity" separator=",">
(#{entity.createdTime}, #{entity.gender}, #{entity.state}, #{entity.username}, #{entity.organizationId})
</foreach>
on duplicate key update
created_time = values(created_time) , gender = values(gender) , state = values(state) , username =
values(username) , organization_id = values(organization_id)
</insert>
</mapper>

View File

@ -0,0 +1,23 @@
package com.cmhi.cf.authentication;
import com.cmhi.cf.authentication.misc.JwtUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
@Slf4j
public class JwtUtilsTest {
@Resource
private JwtUtils jwtUtils;
@Test
public void CreateJwtTest() {
String jwt = jwtUtils.getToken(120L);
log.info("JWT: {}", jwt);
Assertions.assertNotNull(jwt);
}
}

View File

@ -0,0 +1,29 @@
package com.cmhi.cf.db;
import com.cmhi.cf.database.authentication.mapper.UserMapper;
import com.cmhi.cf.database.authentication.entity.User;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@SpringBootTest
@Transactional
@Rollback
@Slf4j
public class AuthDatabaseTest {
@Resource
private UserMapper userMapper;
@Test
void testUserSelect() {
List<User> users = userMapper.selectAll();
Assertions.assertFalse(users.isEmpty());
log.info("Items: {}", users);
}
}