OCT 1. SpringSecurity 增加认证拦截
This commit is contained in:
parent
68fc180711
commit
ea53882c71
|
@ -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
|
||||
|
|
|
@ -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
73
pom.xml
|
@ -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>
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
@ -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> {
|
||||
|
||||
}
|
||||
|
|
@ -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> {
|
||||
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
||||
}
|
||||
|
|
@ -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 {
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue