引入 multi-tenant library 并完成初步测试
diff --git a/payapi/Dockerfile b/payapi/Dockerfile
index 28f3e81..6975293 100644
--- a/payapi/Dockerfile
+++ b/payapi/Dockerfile
@@ -1,9 +1,13 @@
FROM openjdk:8
-COPY payapi-1.jar /opt/payapi/payapi.jar
+ARG BUILD_VERSION
+
+ENV EXEC_JAR=payapi-$BUILD_VERSION.jar
+
+COPY payapi-${BUILD_VERSION}.jar /opt/payapi/
EXPOSE 8080
WORKDIR /opt/payapi
-CMD ["java" , "-jar", "payapi.jar"]
+CMD java -jar ${EXEC_JAR}
diff --git a/payapi/build.gradle b/payapi/build.gradle
index 9dcd2e4..d8f169c 100644
--- a/payapi/build.gradle
+++ b/payapi/build.gradle
@@ -14,14 +14,15 @@
println("Build version: $buildVersion")
+
bootJar {
enabled = true
mainClassName = payapiStartClass
- def standalone = ""
- if (rootProject.hasProperty("no-multi-tenant")) {
- standalone = "-stangalone-"
- }
- archiveFileName = "${project.name}${standalone}-${buildVersion}.${archiveExtension.getOrElse('.jar')}"
+// def standalone = ""
+// if (rootProject.hasProperty("no-multi-tenant")) {
+// standalone = "-stangalone-"
+//
+ archiveFileName = "${project.name}-${buildVersion}.${archiveExtension.getOrElse('.jar')}"
manifest {
attributes("Payapi-Version": buildVersion,
"Payapi-Buildtime": buildTime)
@@ -51,12 +52,11 @@
}
println("Docker image tag : ${imageVersion}")
name "${dockerRegistry}/payapi:${imageVersion}"
- println(jar.archiveFile.get())
- files jar.archiveFile.get()
+ println(bootJar.archiveFile.get())
+ files bootJar.archiveFile.get()
+ buildArgs([BUILD_VERSION: "${buildVersion}"])
}
-docker.dependsOn(jar)
-
configurations {
developmentOnly
runtimeClasspath {
@@ -107,6 +107,7 @@
implementation "com.supwisdom:multi-tenant-core:${multiTenantLibVersion}"
implementation "com.supwisdom:multi-tenant-datasource:${multiTenantLibVersion}"
+ implementation "com.supwisdom:multi-tenant-jwt:${multiTenantLibVersion}"
implementation "org.bitbucket.b_c:jose4j:${jose4jVersion}"
implementation files("libs/masmgc.sdk.sms-0.0.1-SNAPSHOT.jar")
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/core/JwtConfig.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/core/JwtConfig.java
deleted file mode 100644
index 85167fd..0000000
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/core/JwtConfig.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.supwisdom.dlpay.framework.core;
-
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-public class JwtConfig {
- @Value("${jwt.secret}")
- private String secret;
- @Value("${jwt.expiration:3600}")
- private Long expiration = 3600L;
- @Value("${jwt.header:Authorization}")
- private String header = "Authorization";
- @Value("${jwt.token_header:Bearer }")
- private String tokenHeader = "Bearer ";
-
- @Value("${jwt.multitenant:false}")
- private Boolean multiTenant = false;
-
- public String getSecret() {
- return secret;
- }
-
- public Long getExpiration() {
- return expiration;
- }
-
- public String getHeader() {
- return header;
- }
-
- public String getTokenHeader() {
- return tokenHeader;
- }
-
- public void setExpiration(Long expiration) {
- this.expiration = expiration;
- }
-
- public Boolean getMultiTenant() {
- return multiTenant;
- }
-
- public void setMultiTenant(Boolean multiTenant) {
- this.multiTenant = multiTenant;
- }
-}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/core/JwtToken.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/core/JwtToken.java
deleted file mode 100644
index 072ea5d..0000000
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/core/JwtToken.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.supwisdom.dlpay.framework.core;
-
-import org.jose4j.jwt.NumericDate;
-
-public class JwtToken {
- private String jti;
- private NumericDate expiration;
- private String jwtToken;
-
- public JwtToken(String jti, String jwtToken, NumericDate exp) {
- this.jti = jti;
- this.jwtToken = jwtToken;
- this.expiration = exp;
- }
-
- public String getJti() {
- return jti;
- }
-
- public void setJti(String jti) {
- this.jti = jti;
- }
-
- public String getJwtToken() {
- return jwtToken;
- }
-
- public void setJwtToken(String jwtToken) {
- this.jwtToken = jwtToken;
- }
-
- public NumericDate getExpiration() {
- return expiration;
- }
-
- public void setExpiration(NumericDate expiration) {
- this.expiration = expiration;
- }
-}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/core/JwtTokenUtil.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/core/JwtTokenUtil.java
deleted file mode 100644
index 71f65bf..0000000
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/core/JwtTokenUtil.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.supwisdom.dlpay.framework.core;
-
-import com.supwisdom.dlpay.framework.util.Constants;
-import org.jose4j.jwa.AlgorithmConstraints;
-import org.jose4j.jwk.JsonWebKey;
-import org.jose4j.jws.AlgorithmIdentifiers;
-import org.jose4j.jws.JsonWebSignature;
-import org.jose4j.jwt.JwtClaims;
-import org.jose4j.jwt.MalformedClaimException;
-import org.jose4j.jwt.consumer.InvalidJwtException;
-import org.jose4j.jwt.consumer.JwtConsumer;
-import org.jose4j.jwt.consumer.JwtConsumerBuilder;
-import org.jose4j.lang.JoseException;
-import org.springframework.security.core.userdetails.UserDetails;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class JwtTokenUtil {
- private JwtConfig jwtConfig;
-
- public JwtTokenUtil(JwtConfig config) {
- this.jwtConfig = config;
- }
-
- public String getHeader() {
- return jwtConfig.getHeader();
- }
-
- public JwtToken generateToken(Map<String, Object> params) throws JoseException, MalformedClaimException {
- JwtClaims claims = new JwtClaims();
- claims.setIssuer(params.get("issuer").toString()); // who creates the token and signs it
- if (params.get("audience") != null) {
- claims.setAudience(params.get("audience").toString());
- }
- claims.setExpirationTimeMinutesInTheFuture(jwtConfig.getExpiration() / 60); // time when the token will expire (10 minutes from now)
- claims.setGeneratedJwtId();
- claims.setIssuedAtToNow(); // when the token was issued/created (now)
- claims.setNotBeforeMinutesInThePast(2); // time before which the token is not yet valid (2 minutes ago)
- if (params.get("subject") != null) {
- claims.setSubject(params.get("subject").toString()); // the subject/principal is whom the token is about
- }
- if (params.get(Constants.JWT_CLAIM_AUTHORITIES) != null) {
- claims.setClaim(Constants.JWT_CLAIM_AUTHORITIES, params.get(Constants.JWT_CLAIM_AUTHORITIES));
- }
- if (params.get(Constants.JWT_CLAIM_UID) != null) {
- claims.setClaim(Constants.JWT_CLAIM_UID, params.get(Constants.JWT_CLAIM_UID));
- }
- if (params.get(Constants.JWT_CLAIM_TENANTID) != null) {
- claims.setClaim(Constants.JWT_CLAIM_TENANTID, params.get(Constants.JWT_CLAIM_TENANTID));
- }
- /*
- claims.setClaim("email", "mail@example.com"); // additional claims/attributes about the subject can be added
- List<String> groups = Arrays.asList("group-one", "other-group", "group-three");
- claims.setStringListClaim("groups", groups); // multi-valued claims work too and will end up as a JSON array
- */
-
- Map<String, Object> keySpec = new HashMap<>();
- keySpec.put("kty", "oct");
- keySpec.put("k", jwtConfig.getSecret());
- JsonWebKey key = JsonWebKey.Factory.newJwk(keySpec);
- JsonWebSignature jws = new JsonWebSignature();
- jws.setPayload(claims.toJson());
- jws.setKey(key.getKey());
- jws.setKeyIdHeaderValue(key.getKeyId());
- jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA256);
- return new JwtToken(claims.getJwtId(), jws.getCompactSerialization(), claims.getExpirationTime());
- }
-
- public JwtToken generateToken(UserDetails userDetails) throws JoseException, MalformedClaimException {
- Map<String, Object> claims = new HashMap<>();
- claims.put("uid", userDetails.getUsername());
- return generateToken(claims);
- }
-
- public Map<String, Object> verifyToken(String token) throws JoseException, InvalidJwtException {
- Map<String, Object> keySpec = new HashMap<>();
- keySpec.put("kty", "oct");
- keySpec.put("k", jwtConfig.getSecret());
- JsonWebKey key = JsonWebKey.Factory.newJwk(keySpec);
- JwtConsumer jwtConsumer = new JwtConsumerBuilder()
- .setRequireExpirationTime() // the JWT must have an expiration time
- .setAllowedClockSkewInSeconds(30) // allow some leeway in validating time based claims to account for clock skew
- .setVerificationKey(key.getKey()) // verify the signature with the public key
- .setSkipDefaultAudienceValidation()
- .setJwsAlgorithmConstraints( // only allow the expected signature algorithm(s) in the given context
- new AlgorithmConstraints(org.jose4j.jwa.AlgorithmConstraints.ConstraintType.WHITELIST, // which is only RS256 here
- AlgorithmIdentifiers.HMAC_SHA256))
- .build(); // create the JwtConsumer instance
-
- // Validate the JWT and process it to the Claims
- JwtClaims jwtClaims = jwtConsumer.processToClaims(token);
- return jwtClaims.getClaimsMap();
- }
-}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/JwtRedis.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/JwtRedis.java
deleted file mode 100644
index d32ff8e..0000000
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/JwtRedis.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.supwisdom.dlpay.framework.domain;
-
-import org.springframework.data.annotation.Id;
-import org.springframework.data.redis.core.RedisHash;
-import org.springframework.data.redis.core.TimeToLive;
-
-
-@RedisHash(value = "api_jwt")
-public class JwtRedis {
- @Id
- String jti;
-
- String status;
-
- String uid;
-
- @TimeToLive
- Long expiration;
-
- public String getJti() {
- return jti;
- }
-
- public void setJti(String jti) {
- this.jti = jti;
- }
-
- public String getStatus() {
- return status;
- }
-
- public void setStatus(String status) {
- this.status = status;
- }
-
- public Long getExpiration() {
- return expiration;
- }
-
- public void setExpiration(Long expiration) {
- this.expiration = expiration;
- }
-
- public String getUid() {
- return uid;
- }
-
- public void setUid(String uid) {
- this.uid = uid;
- }
-}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TTenantUserDB.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TTenantUserDB.java
index 7df05a7..6f3258f 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TTenantUserDB.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TTenantUserDB.java
@@ -2,13 +2,14 @@
import javax.persistence.*;
import javax.validation.constraints.NotNull;
+import java.io.Serializable;
@Entity
@Table(name = "t_tenant_user_db", schema = "public",
indexes = {@Index(name = "tenant_db_dbid_idx", columnList = "dbid"),
@Index(name = "tenant_db_schema_idx", columnList = "schema"),
@Index(name = "tenant_db_idx2", columnList = "dbid, schema", unique = true)})
-public class TTenantUserDB {
+public class TTenantUserDB implements Serializable {
@Id
@Column(name = "id", length = 32)
private String id;
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/redisrepo/ApiJwtRepository.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/redisrepo/ApiJwtRepository.java
deleted file mode 100644
index 3371b31..0000000
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/redisrepo/ApiJwtRepository.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.supwisdom.dlpay.framework.redisrepo;
-
-import com.supwisdom.dlpay.framework.domain.JwtRedis;
-import org.springframework.data.repository.CrudRepository;
-import org.springframework.stereotype.Repository;
-
-public interface ApiJwtRepository extends CrudRepository<JwtRedis, String> {
-}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/tenant/MultiTenantUserAdapter.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/tenant/MultiTenantUserAdapter.java
index fddcfd7..1a0a92b 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/tenant/MultiTenantUserAdapter.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/tenant/MultiTenantUserAdapter.java
@@ -5,6 +5,7 @@
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Primary;
+import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
@@ -17,10 +18,13 @@
public class MultiTenantUserAdapter implements AbstractTenantUserOperator {
private static final String DOMAIN_SEP = "@";
- private TenantSessionHelper tenantSessionHelper;
+ private final TenantSessionHelper tenantSessionHelper;
- public MultiTenantUserAdapter(TenantSessionHelper tenantSessionHelper) {
+ private final RedisTemplate<String, String> redisTemplate;
+
+ public MultiTenantUserAdapter(TenantSessionHelper tenantSessionHelper, RedisTemplate<String, String> redisTemplate) {
this.tenantSessionHelper = tenantSessionHelper;
+ this.redisTemplate = redisTemplate;
}
@Override
@@ -30,7 +34,15 @@
if (StringUtils.isEmpty(domain)) {
tenantSessionHelper.setSessionTenantById(Constants.DEFAULT_TENANTID);
} else {
- tenantSessionHelper.setSessionTenantById(domain);
+ String schema = redisTemplate.opsForValue().get(domain);
+ if (StringUtils.isEmpty(schema)) {
+ schema = "public";
+ }
+ String tenantId = redisTemplate.opsForValue().get(schema);
+ if (StringUtils.isEmpty(schema)) {
+ tenantId = "default";
+ }
+ tenantSessionHelper.setSessionTenantById(tenantId);
}
if (StringUtils.isEmpty(realname)) {
throw new UsernameNotFoundException("管理员不存在");
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
index 4b88ed0..4cd2abe 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
@@ -3,15 +3,21 @@
import com.supwisdom.dlpay.framework.service.TenantService
import com.supwisdom.dlpay.framework.tenant.TenantCacheKeyGen
import com.supwisdom.dlpay.framework.util.Constants
+import com.supwisdom.multitenant.TenantContextHolder
import com.supwisdom.multitenant.TenantDetails
import com.supwisdom.multitenant.TenantDetailsProvider
-import com.supwisdom.multitenant.TenantSessionData
import com.supwisdom.multitenant.annotations.EnableHttpHeaderTenantInterceptor
import com.supwisdom.multitenant.annotations.EnableSessionTenantInterceptor
+import com.supwisdom.multitenant.exceptions.TenantNotDefException
+import com.supwisdom.multitenant.jwt.JwtTenantConfigAdapter
+import com.supwisdom.multitenant.jwt.annotations.EnableJwtTenantInterceptor
+import com.supwisdom.multitenant.jwt.config.JwtTenantConfig
+import com.supwisdom.multitenant.jwt.config.JwtToken
import io.lettuce.core.ReadFrom
import mu.KotlinLogging
import net.javacrumbs.shedlock.core.LockProvider
import net.javacrumbs.shedlock.provider.redis.spring.RedisLockProvider
+import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.SpringApplication
@@ -37,6 +43,7 @@
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer
import org.springframework.data.redis.serializer.StringRedisSerializer
import org.springframework.http.client.SimpleClientHttpRequestFactory
import org.springframework.scheduling.annotation.EnableScheduling
@@ -72,6 +79,15 @@
}
@Bean
+ fun redisTempalte(factor: RedisConnectionFactory): RedisTemplate<String, JwtToken> {
+ val template = RedisTemplate<String, JwtToken>();
+ template.setConnectionFactory(factor)
+ template.keySerializer = StringRedisSerializer()
+ template.valueSerializer = Jackson2JsonRedisSerializer(JwtToken::class.java)
+ return template
+ }
+
+ @Bean
fun lockProvider(connectionFactory: RedisConnectionFactory): LockProvider {
return RedisLockProvider(connectionFactory, "prod")
}
@@ -156,6 +172,8 @@
fun restTemplate(factory: SimpleClientHttpRequestFactory): RestTemplate {
return RestTemplate(factory)
}
+
+
}
@@ -172,34 +190,58 @@
class MyTenantDetailsProvider : TenantDetailsProvider {
@Autowired
private lateinit var tenantService: TenantService
+ @Autowired
+ private lateinit var redisTemplate: RedisTemplate<String, String>
+
+ private val logger = KotlinLogging.logger { }
private val defaultTenant = TenantDetails().apply {
id = Constants.DEFAULT_TENANTID
dbSchema = "public"
dataCenter = "default"
+ enabled = true
}
override fun defaultTenant(): TenantDetails {
return defaultTenant
}
- override fun createDetailsById(id: String?): TenantDetails {
- return tenantService.findByTenantId(id)?.let { catalog ->
- TenantDetails().apply {
- this.id = catalog.id
- dbSchema = catalog.schema
- dataCenter = "default"
- }
- } ?: return defaultTenant
+ override fun createDetailsById(id: String): TenantDetails {
+ logger.debug { "find tenant id <$id> ..." }
+ val schema = redisTemplate.opsForValue().get(id) ?: return defaultTenant
+ return TenantDetails().apply {
+ this.id = id
+ dbSchema = schema
+ dataCenter = "default"
+ enabled = true
+ }
+ }
+}
+
+@Component
+class MyTenantJwtConfigAdapter : JwtTenantConfigAdapter {
+ @Value("\${jwt.secret}")
+ private lateinit var jwtSecret: String;
+
+ override fun getConfig(): JwtTenantConfig {
+ if (TenantContextHolder.getContext().tenant == null) {
+ throw TenantNotDefException("未定义Tenant id")
+ }
+ return JwtTenantConfig().apply {
+ this.tenantId = TenantContextHolder.getContext().tenant.id
+ this.secret = jwtSecret
+ }
}
}
@SpringBootApplication
@EnableDiscoveryClient
@EnableScheduling
+@EnableSchedulerLock(defaultLockAtMostFor = "PT15m")
@EnableCaching
@EnableHttpHeaderTenantInterceptor
@EnableSessionTenantInterceptor
+@EnableJwtTenantInterceptor
@ServletComponentScan
class PayApiApplication : SpringBootServletInitializer() {
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt
index deabb41..22c1490 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt
@@ -5,21 +5,20 @@
import com.supwisdom.dlpay.api.bean.ApiLoginResponse
import com.supwisdom.dlpay.exception.TransactionCheckException
import com.supwisdom.dlpay.framework.ResponseBodyBuilder
-import com.supwisdom.dlpay.framework.core.JwtConfig
-import com.supwisdom.dlpay.framework.core.JwtTokenUtil
import com.supwisdom.dlpay.framework.dao.ApiClientDao
import com.supwisdom.dlpay.framework.dao.TenantConfigDao
import com.supwisdom.dlpay.framework.domain.ApiClientRedis
-import com.supwisdom.dlpay.framework.domain.JwtRedis
import com.supwisdom.dlpay.framework.domain.TOperator
import com.supwisdom.dlpay.framework.redisrepo.ApiClientRepository
-import com.supwisdom.dlpay.framework.redisrepo.ApiJwtRepository
import com.supwisdom.dlpay.framework.security.validate.ImageCodeUtil
import com.supwisdom.dlpay.framework.security.validate.VerifyCode
import com.supwisdom.dlpay.framework.service.CommonService
import com.supwisdom.dlpay.framework.service.SystemUtilService
import com.supwisdom.dlpay.framework.util.*
import com.supwisdom.dlpay.system.service.FunctionService
+import com.supwisdom.multitenant.jwt.JwtRequestData
+import com.supwisdom.multitenant.jwt.JwtTenantService
+import com.supwisdom.multitenant.jwt.JwtTokenBuilder
import mu.KotlinLogging
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.redis.connection.RedisConnectionFactory
@@ -37,7 +36,9 @@
import org.springframework.web.bind.annotation.*
import org.springframework.web.context.request.ServletWebRequest
import java.io.IOException
+import java.time.Instant
import java.util.*
+import javax.annotation.Resource
import javax.imageio.ImageIO
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
@@ -50,19 +51,19 @@
lateinit var apiClientRepository: ApiClientRepository
@Autowired
- lateinit var apiJwtRepository: ApiJwtRepository
-
- @Autowired
lateinit var apiClientDao: ApiClientDao
@Autowired
lateinit var systemUtil: SystemUtilService
@Autowired
- lateinit var jwtConfig: JwtConfig
+ private lateinit var tetantConfigDao: TenantConfigDao
@Autowired
- private lateinit var tetantConfigDao: TenantConfigDao
+ private lateinit var jwtTenantService: JwtTenantService
+
+ @Resource(name = "jwtRequestData")
+ private lateinit var jwtRequestData: JwtRequestData
@GetMapping(value = ["/gettoken", "/gettoken/{clientid}"])
fun loginInit(appid: String, @PathVariable clientid: String?,
@@ -114,24 +115,16 @@
return apiClientRepository.findById(requestId).let {
if (it.isPresent && checkSecretToken(it.get(), secret)) {
apiClientRepository.deleteById(requestId)
- val token = JwtTokenUtil(jwtConfig).generateToken(
- mapOf(Constants.JWT_CLAIM_UID to appid,
- "issuer" to "payapi",
- "audience" to (clientid ?: appid),
- Constants.JWT_CLAIM_TENANTID to it.get().tenantId,
- Constants.JWT_CLAIM_AUTHORITIES to it.get().roles.split(";")))
- JwtRedis().apply {
- jti = token.jti
- uid = appid
- status = TradeDict.JWT_STATUS_NORMAL
- expiration = token.expiration.valueInMillis
- }.apply {
- apiJwtRepository.save(this)
- }
-
+ val builder = JwtTokenBuilder.create()
+ .uid(appid)
+ .issuer("payapi")
+ .audience(listOf(clientid ?: appid))
+ .tenantId(it.get().tenantId)
+ .authorities(it.get().roles.split(";"))
+ val token = jwtTenantService.generate(builder)
ResponseEntity.ok(ResponseBodyBuilder.create()
- .success(ApiLoginResponse(token.jwtToken,
- appid, DateUtil.getUTCTime(token.expiration.valueInMillis))))
+ .success(ApiLoginResponse(token.get().jwt,
+ appid, Instant.ofEpochSecond(token.get().expiration).toString())))
} else {
ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()
}
@@ -140,38 +133,29 @@
@GetMapping("/refresh")
fun refresh(request: HttpServletRequest): ResponseEntity<Any> {
- val auth = request.getHeader(jwtConfig.header) ?: ""
- if (!auth.startsWith(jwtConfig.tokenHeader)) {
- return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()
- }
- val jwt = JwtTokenUtil(jwtConfig).verifyToken(auth.substring(jwtConfig.tokenHeader.length))
- val appid = jwt["uid"] as String
- val result = apiClientDao.findByAppid(appid)?.let {
- if (it.status == TradeDict.STATUS_NORMAL) {
- // 新证书
- val token = JwtTokenUtil(jwtConfig).generateToken(
- mapOf(Constants.JWT_CLAIM_UID to appid,
- "issuer" to "payapi",
- "audience" to jwt["audience"],
- Constants.JWT_CLAIM_AUTHORITIES to it.roles.split(";")))
- JwtRedis().apply {
- jti = token.jti
- uid = appid
- status = TradeDict.JWT_STATUS_NORMAL
- expiration = token.expiration.valueInMillis
- }.apply {
- apiJwtRepository.save(this)
- }
+ val jwt = jwtRequestData.jwtToken
+ ?: return ResponseEntity.ok(ResponseBodyBuilder.create().fail(TradeErrorCode.INPUT_DATA_ERROR,
+ "jwt unauthorized"))
- ResponseEntity.ok(ResponseBodyBuilder.create()
- .success(ApiLoginResponse(token.jwtToken,
- appid, DateUtil.getUTCTime(token.expiration.valueInMillis))))
- } else {
- ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(mapOf("msg" to "appid error"))
- }
- } ?: ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(mapOf("msg" to "appid error"))
- @Suppress("UNCHECKED_CAST")
- return result as ResponseEntity<Any>
+ val appid = jwt.uid
+ // 新证书
+ val builder = JwtTokenBuilder.create()
+ .uid(appid)
+ .issuer(jwt.issuer)
+ .audience(jwt.audience)
+ .tenantId(jwt.tenantId)
+ .authorities(jwt.authorities)
+ val token = jwtTenantService.generate(builder)
+
+ return if (token.isPresent) {
+ ResponseEntity.ok(ResponseBodyBuilder.create()
+ .success(ApiLoginResponse(token.get().jwt,
+ appid, Instant.ofEpochSecond(token.get().expiration).toString())))
+ } else {
+
+ ResponseEntity.ok(ResponseBodyBuilder.create()
+ .fail(TradeErrorCode.INPUT_DATA_ERROR, "JWT生成错误"))
+ }
}
}
@@ -208,25 +192,26 @@
@RestController
class UserInforController {
@Autowired
- lateinit var jwtConfig: JwtConfig
- @Autowired
private lateinit var redisConnectionFactory: RedisConnectionFactory
+ @Resource(name = "jwtRequestData")
+ private lateinit var jwtRequestData: JwtRequestData
+
@RequestMapping("/userinfor")
fun user(@RequestParam("access_token") access_token: String?,
@RequestHeader(Constants.HEADER_AUTHORIZATION) auth: String?): ResponseEntity<Any> {
if (access_token.isNullOrEmpty() && auth.isNullOrEmpty()) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()
}
- var jwt: String
- if(!auth.isNullOrEmpty()){
- jwt = auth.substring(jwtConfig.tokenHeader.length)
- }else{
- jwt = access_token!!
+ val jwt = if (!auth.isNullOrEmpty()) {
+ jwtRequestData.jwtToken.jwt
+ } else {
+ access_token!!
}
- val obj: OAuth2Authentication? = RedisTokenStore(redisConnectionFactory).readAuthentication(jwt) ?: return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()
+ val obj: OAuth2Authentication? = RedisTokenStore(redisConnectionFactory).readAuthentication(jwt)
+ ?: return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()
val user = obj!!.userAuthentication.principal as UserDetails
- if(user.username.isNullOrEmpty()){
+ if (user.username.isNullOrEmpty()) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()
}
return ResponseEntity.status(HttpStatus.OK).body("""{"name":"${user.username}"}""")
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/service/impl/framework_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/service/impl/framework_service_impl.kt
index b997a61..e5d2858 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/service/impl/framework_service_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/service/impl/framework_service_impl.kt
@@ -2,55 +2,42 @@
import com.jcabi.manifests.Manifests
import com.supwisdom.dlpay.exception.TransactionProcessException
-import com.supwisdom.dlpay.framework.core.JwtConfig
-import com.supwisdom.dlpay.framework.core.JwtTokenUtil
import com.supwisdom.dlpay.framework.dao.ApiClientDao
import com.supwisdom.dlpay.framework.service.CommonService
import com.supwisdom.dlpay.framework.util.StringUtil
import com.supwisdom.dlpay.framework.util.TradeErrorCode
+import com.supwisdom.multitenant.jwt.JwtRequestData
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
+import javax.annotation.Resource
import javax.servlet.http.HttpServletRequest
@Service
class CommonServiceImpl : CommonService {
@Autowired
- lateinit var jwtConfig: JwtConfig
- @Autowired
lateinit var apiClientDao: ApiClientDao
- private var jwtUtil: JwtTokenUtil? = null
-
- private fun getUtil(): JwtTokenUtil {
- if (jwtUtil == null) {
- jwtUtil = JwtTokenUtil((jwtConfig))
- }
- return jwtUtil as JwtTokenUtil
- }
+ @Resource(name = "jwtRequestData")
+ private lateinit var jwtRequestData: JwtRequestData
override fun getSystemVersion(): String {
return try {
- var ver = Manifests.read("Payapi-Version") ?: "version 1.0"
+ var ver = Manifests.read("Payapi-Version") ?: "version 1.0"
ver += Manifests.read("Payapi-Buildtime") ?: "no"
ver
} catch (ex: Exception) {
-// ex.printStackTrace()
"unknown"
}
}
override fun getRequestAppid(request: HttpServletRequest): String {
- request.getHeader(jwtConfig.header).let {
- if (null != it && it.startsWith(jwtConfig.tokenHeader)) {
- val claims = getUtil().verifyToken(it.substring(jwtConfig.tokenHeader.length))
- val uid = claims["uid"]?.toString()
- if (!StringUtil.isEmpty(uid)) {
- return uid as String
- }
+ jwtRequestData.jwtToken?.also {
+ val uid = it.uid
+ if (!StringUtil.isEmpty(uid)) {
+ return uid as String
}
-
- throw TransactionProcessException(TradeErrorCode.BUSINESS_APPID_NOTFOUND, "APPID未找到") //报错
}
+ throw TransactionProcessException(TradeErrorCode.BUSINESS_APPID_NOTFOUND, "APPID未找到") //报错
}
override fun getAppidSecretByRequest(request: HttpServletRequest): String {
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/AuthLoginHandler.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/AuthLoginHandler.kt
index c795cbd..6317ab3 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/AuthLoginHandler.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/AuthLoginHandler.kt
@@ -3,16 +3,14 @@
import com.fasterxml.jackson.databind.ObjectMapper
import com.supwisdom.dlpay.api.bean.JsonResult
import com.supwisdom.dlpay.api.service.UserService
-import com.supwisdom.dlpay.framework.core.JwtConfig
-import com.supwisdom.dlpay.framework.core.JwtTokenUtil
-import com.supwisdom.dlpay.framework.domain.JwtRedis
-import com.supwisdom.dlpay.framework.redisrepo.ApiJwtRepository
import com.supwisdom.dlpay.framework.service.SystemUtilService
import com.supwisdom.dlpay.framework.util.*
import com.supwisdom.dlpay.mobile.dao.MobileUserDao
import com.supwisdom.dlpay.mobile.domain.TBMobileUser
import com.supwisdom.dlpay.mobile.exception.UserLoginFailException
import com.supwisdom.dlpay.mobile.service.MobileApiService
+import com.supwisdom.multitenant.jwt.JwtTenantService
+import com.supwisdom.multitenant.jwt.JwtTokenBuilder
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.HttpStatus
import org.springframework.security.authentication.BadCredentialsException
@@ -34,40 +32,30 @@
@Autowired
lateinit var objectMapper: ObjectMapper
@Autowired
- lateinit var jwtConfig: JwtConfig
- @Autowired
- lateinit var apiJwtRepository: ApiJwtRepository
- @Autowired
lateinit var systemUtilService: SystemUtilService
@Autowired
lateinit var userService: UserService
+ @Autowired
+ lateinit var jwtTenantService: JwtTenantService
+
override fun onAuthenticationSuccess(request: HttpServletRequest, response: HttpServletResponse, authentication: Authentication) {
val platform = request.getParameter("platform")
logger.error(platform)
val temp = authentication.principal as TBMobileUser
val user = mobileApiService.findUserById(temp.uid)
- val exp = systemUtilService.getSysparaValueAsInt(SysparaUtil.MOBILE_LOGIN_EXPIRE_IN_SECONDS,60*60*24*3)
- jwtConfig.expiration = exp.toLong()
+ val exp = systemUtilService.getSysparaValueAsInt(SysparaUtil.MOBILE_LOGIN_EXPIRE_IN_SECONDS, 60 * 60 * 24 * 3)
if (user != null) {
//TODO 从数据取jwtConfig.expiration
- val token = JwtTokenUtil(jwtConfig).generateToken(
- mapOf("uid" to user.uid, "issuer" to "payapi",
- "audience" to user.loginid,
- Constants.JWT_CLAIM_TENANTID to "mobile",
- Constants.JWT_CLAIM_AUTHORITIES to temp.authorities))
- val jwt = JwtRedis().apply {
- jti = token.jti
- uid = user.loginid
- status = TradeDict.JWT_STATUS_NORMAL
- expiration = token.expiration.valueInMillis
- }.apply {
- //删除之前的token
- if (!user.jti.isNullOrEmpty()) {
- apiJwtRepository.deleteById(user.jti!!)
- }
- apiJwtRepository.save(this)
- }
+ val builder = JwtTokenBuilder.create()
+ .expiration(exp.toLong())
+ .issuer("payapi")
+ .uid(user.uid)
+ .tenantId("mobile")
+ .authorities(temp.authorities?.toList() ?: listOf<Any>())
+ val token = jwtTenantService.generate(builder)
+
+ val jwt = token.get()
if (user.loginpwderror > 0) {
user.loginpwderror = 0
user.loginpwderrortime = null
@@ -77,32 +65,32 @@
user.jti = jwt.jti
mobileApiService.saveUser(user)
var payseted = false
- if(!user.paypwd.isNullOrEmpty()){
+ if (!user.paypwd.isNullOrEmpty()) {
payseted = true
}
var name = ""
- var signed=""
+ var signed = ""
if (!user.userid.isNullOrEmpty()) {
val person = userService.findOnePersonByUserid(user.userid!!)
var card = mobileApiService.findCardByUserid(user.userid!!)
name = person.name
- if(card!=null&&card.signed){
+ if (card != null && card.signed) {
signed = TradeDict.STATUS_YES
}
}
response.status = HttpStatus.OK.value()
response.contentType = "application/json;charset=UTF-8"
response.writer.write(objectMapper.writeValueAsString(JsonResult.ok()
- .put("token", token.jwtToken)
- ?.put("expire",token.expiration.valueInMillis)
- ?.put("now",System.currentTimeMillis())
+ .put("token", jwt.jwt)
+ ?.put("expire", jwt.expiration)
+ ?.put("now", System.currentTimeMillis())
?.put("tenantid", "mobile")
?.put("name", name)
?.put("uid", user.uid)
?.put("phone", StringUtil.phoneReplace(user.phone))
- ?.put("paypwdset",payseted)
+ ?.put("paypwdset", payseted)
?.put("signed", signed)
- ?.put("userid",if(user.userid.isNullOrEmpty()) "" else user.userid)))
+ ?.put("userid", if (user.userid.isNullOrEmpty()) "" else user.userid)))
} else {
throw UserLoginFailException("登录错误")
}
@@ -128,7 +116,7 @@
else -> exception.message!!
}
val temp = request.getParameter("username")
- if(!temp.isNullOrEmpty()) {
+ if (!temp.isNullOrEmpty()) {
mobileUserDao.findByLoginid(temp)?.let {
if (it.loginpwderror == 0) {
it.loginpwderror = 0
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
index da66271..26289f6 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
@@ -6,10 +6,6 @@
import com.supwisdom.dlpay.api.service.QRCodeService
import com.supwisdom.dlpay.api.service.UserService
import com.supwisdom.dlpay.api.util.MobileNumberCheck
-import com.supwisdom.dlpay.framework.core.JwtConfig
-import com.supwisdom.dlpay.framework.core.JwtTokenUtil
-import com.supwisdom.dlpay.framework.domain.JwtRedis
-import com.supwisdom.dlpay.framework.redisrepo.ApiJwtRepository
import com.supwisdom.dlpay.framework.service.SystemUtilService
import com.supwisdom.dlpay.framework.util.*
import com.supwisdom.dlpay.framework.util.Dictionary
@@ -18,6 +14,9 @@
import com.supwisdom.dlpay.system.service.DictionaryProxy
import com.supwisdom.dlpay.util.ConstantUtil
import com.supwisdom.dlpay.util.RSAKeysGenerate
+import com.supwisdom.multitenant.jwt.JwtRequestData
+import com.supwisdom.multitenant.jwt.JwtTenantService
+import com.supwisdom.multitenant.jwt.JwtTokenBuilder
import mu.KotlinLogging
import org.apache.commons.lang.StringUtils
import org.jose4j.jwt.ReservedClaimNames
@@ -35,6 +34,7 @@
import org.springframework.web.bind.annotation.RequestParam
import java.time.Duration
import java.util.*
+import javax.annotation.Resource
@RestController
@@ -45,11 +45,10 @@
@Autowired
lateinit var redisTemplate: RedisTemplate<String, String>
@Autowired
- lateinit var jwtConfig: JwtConfig
- @Autowired
- lateinit var apiJwtRepository: ApiJwtRepository
- @Autowired
lateinit var systemUtilService: SystemUtilService
+ @Autowired
+ lateinit var jwtTenantService: JwtTenantService
+
val logger = KotlinLogging.logger { }
@RequestMapping("/time")
@@ -139,7 +138,7 @@
}
user.status = TradeDict.STATUS_NORMAL
user.registerplatform = platform
- if(!user.registerplatform.isNullOrEmpty()){
+ if (!user.registerplatform.isNullOrEmpty()) {
user.lastloginplatform = user.registerplatform!!.split(",")[1]
}
user.devuid = uuid
@@ -181,26 +180,18 @@
val encoder = BCryptPasswordEncoder()
user!!.loginpwd = encoder.encode(pwd)
val exp = systemUtilService.getSysparaValueAsInt(SysparaUtil.MOBILE_LOGIN_EXPIRE_IN_SECONDS, 60 * 60 * 24 * 3)
- jwtConfig.expiration = exp.toLong()
+// jwtConfig.expiration = exp.toLong()
val authorities: Collection<GrantedAuthority> = AuthorityUtils.createAuthorityList("ROLE_USER")
user.auths = authorities
- val token = JwtTokenUtil(jwtConfig).generateToken(
- mapOf("uid" to user.uid, "issuer" to "payapi",
- "audience" to user.loginid,
- Constants.JWT_CLAIM_TENANTID to "mobile",
- Constants.JWT_CLAIM_AUTHORITIES to user.authorities))
- val jwt = JwtRedis().apply {
- jti = token.jti
- uid = user.loginid
- status = TradeDict.JWT_STATUS_NORMAL
- expiration = token.expiration.valueInMillis
- }.apply {
- //删除之前的token
- if (!user.jti.isNullOrEmpty()) {
- apiJwtRepository.deleteById(user.jti!!)
- }
- apiJwtRepository.save(this)
- }
+ val builder = JwtTokenBuilder.create()
+ .expiration(exp.toLong())
+ .uid(user.uid)
+ .issuer("payapi")
+ .tenantId("mobile")
+ .authorities(user.authorities?.toList() ?: listOf<Any>())
+ val token = jwtTenantService.generate(builder)
+ val jwt = token.get()
+
if (user.loginpwderror > 0) {
user.loginpwderror = 0
user.loginpwderrortime = null
@@ -226,9 +217,9 @@
signed = TradeDict.STATUS_YES
}
}
- return JsonResult.ok("OK").put("token", token.jwtToken)
+ return JsonResult.ok("OK").put("token", jwt.jwt)
?.put("userid", if (user.userid.isNullOrEmpty()) "" else user.userid)
- ?.put("expire", token.expiration.valueInMillis)
+ ?.put("expire", jwt.expiration)
?.put("now", System.currentTimeMillis())
?.put("phone", StringUtil.phoneReplace(user.phone))
?.put("paypwdset", payseted)
@@ -252,28 +243,29 @@
@Autowired
lateinit var citizencardPayService: CitizencardPayService
@Autowired
- lateinit var apiJwtRepository: ApiJwtRepository
+ lateinit var qrcodeService: QRCodeService
@Autowired
- lateinit var jwtConfig: JwtConfig
+ lateinit var systemUtilService: SystemUtilService
@Autowired
- lateinit var qrcodeService:QRCodeService
+ lateinit var jwtTenantService: JwtTenantService
+
+ @Resource(name = "jwtRequestData")
+ lateinit var jwtRequestData: JwtRequestData
+
val logger = KotlinLogging.logger { }
@RequestMapping("/idtypes")
fun idtypes(): JsonResult {
- var dict = dictionaryProxy.getDictionaryAsMap(Dictionary.IDTYPE)
+ val dict = dictionaryProxy.getDictionaryAsMap(Dictionary.IDTYPE)
return JsonResult.ok("OK").put("idtypes", dict)!!
}
@RequestMapping("/logout")
- fun logout(@RequestHeader("Authorization") auth: String?): ResponseEntity<Any> {
- if (auth == null) {
- return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()
- }
- val jwt = auth.substring(jwtConfig.tokenHeader.length)
- val claims = JwtTokenUtil(jwtConfig).verifyToken(jwt)
+ fun logout(): ResponseEntity<Any> {
SecurityContextHolder.clearContext()
- apiJwtRepository.deleteById(claims[ReservedClaimNames.JWT_ID].toString())
+ jwtRequestData.jwtToken?.also {
+ jwtTenantService.revoke(it)
+ }
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()
}
@@ -283,42 +275,35 @@
@RequestMapping("/infor")
fun getUserInfor(): JsonResult {
val p = SecurityContextHolder.getContext().authentication
- var user = mobileApiService.findUserById(p.name)
+ val user = mobileApiService.findUserById(p.name)
?: return JsonResult.error("用户不存在,请注册")
- var tk= ""
- if (!user.jti.isNullOrEmpty()) {
- var opt = apiJwtRepository.findById(user.jti!!)
- if(opt.isPresent){
- var jwt = opt.get()
- val cur = System.currentTimeMillis()
- //token 小于12个小时,则更新它
- if(jwt.expiration-cur<1000*60*60*12){
- val token = JwtTokenUtil(jwtConfig).generateToken(
- mapOf("uid" to user.uid, "issuer" to "payapi",
- "audience" to user.loginid,
- Constants.JWT_CLAIM_TENANTID to "mobile",
- Constants.JWT_CLAIM_AUTHORITIES to p.authorities))
- jwt = JwtRedis().apply {
- jti = token.jti
- uid = user.loginid
- status = TradeDict.JWT_STATUS_NORMAL
- expiration = token.expiration.valueInMillis
- }.apply {
- //删除之前的token
- if (!user.jti.isNullOrEmpty()) {
- apiJwtRepository.deleteById(user.jti!!)
- }
- apiJwtRepository.save(this)
- }
- user.jti = jwt.jti
+ var tk = ""
+ jwtRequestData.jwtToken?.also {
+ val currentMillis = System.currentTimeMillis()
+ if (it.expiration - currentMillis < 60 * 60 * 12) {
+ val exp = systemUtilService.getSysparaValueAsInt(
+ SysparaUtil.MOBILE_LOGIN_EXPIRE_IN_SECONDS, 60 * 60 * 24 * 3)
+ val builder = JwtTokenBuilder.create()
+ .expiration(exp.toLong())
+ .uid(user.uid)
+ .issuer("payapi")
+ .tenantId("mobile")
+ .authorities(p.authorities.toList())
+ val token = jwtTenantService.generate(builder)
+ if (token.isPresent) {
+ user.jti = token.get().jti
mobileApiService.saveUser(user)
- tk = token.jwtToken
+ tk = token.get().jwt
+ jwtTenantService.revoke(jwtRequestData.jwtToken)
+ } else {
+ tk = jwtRequestData.jwtToken.jwt
}
}
}
return JsonResult.ok("OK").put("now", System.currentTimeMillis())
?.put("token", tk)!!
}
+
/**
* 验证码生成,内部校验
* */
@@ -625,9 +610,9 @@
?.put("name", name)
?.put("needrebind", needrebind)
?.put("signed", signed)
- ?.put("version","1")
- ?.put("minversion","1")
- ?.put("versionmsg","1")
+ ?.put("version", "1")
+ ?.put("minversion", "1")
+ ?.put("versionmsg", "1")
?.put("userid", if (user.userid.isNullOrEmpty()) "" else user.userid)!!.put("t", t)!!
}
@@ -666,7 +651,7 @@
val pwdtimes = user.checkLoginpwdtime()
if (pwdtimes == -1) {
if (!user.jti.isNullOrEmpty()) {
- apiJwtRepository.deleteById(user.jti!!)
+ jwtTenantService.revoke(jwtRequestData.jwtToken)
}
return JsonResult.error(-1, "原密码错误次数过多,将退出系统,请重新登录系统或点击忘记密码功能找回密码")
} else if (pwdtimes == 1) {
@@ -760,9 +745,9 @@
val user = mobileApiService.findUserById(p.name)
?: return JsonResult.error("用户不存在,请注册")
val resp = qrcodeService.encodeCode(user.uid)
- return if(resp.retcode==0){
+ return if (resp.retcode == 0) {
JsonResult.ok("ok").put("qrcode", resp.retmsg)!!
- }else{
+ } else {
JsonResult.error(resp.retmsg)
}
}
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/security.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/security.kt
index 9db3122..8e1892a 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/security.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/security.kt
@@ -1,18 +1,13 @@
package com.supwisdom.dlpay
-import com.supwisdom.dlpay.framework.core.JwtConfig
-import com.supwisdom.dlpay.framework.core.JwtTokenUtil
import com.supwisdom.dlpay.framework.core.PasswordBCryptConfig
-import com.supwisdom.dlpay.framework.redisrepo.ApiJwtRepository
import com.supwisdom.dlpay.framework.security.MyAuthenticationFailureHandler
import com.supwisdom.dlpay.framework.security.ValidateCodeSecurityConfig
import com.supwisdom.dlpay.framework.service.impl.MultiTenantOperatorDetailService
-import com.supwisdom.dlpay.framework.util.Constants
-import com.supwisdom.dlpay.framework.util.TradeDict
import com.supwisdom.dlpay.mobile.AuthLoginFailHandler
import com.supwisdom.dlpay.mobile.AuthLoginSuccessHandler
import com.supwisdom.dlpay.mobile.service.MobileUserService
-import org.jose4j.jwt.ReservedClaimNames
+import com.supwisdom.multitenant.jwt.JwtRequestData
import org.jose4j.jwt.consumer.InvalidJwtException
import org.jose4j.lang.JoseException
import org.springframework.beans.factory.annotation.Autowired
@@ -42,6 +37,7 @@
import org.springframework.web.filter.OncePerRequestFilter
import java.security.SecureRandom
import java.util.*
+import javax.annotation.Resource
import javax.servlet.FilterChain
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
@@ -50,60 +46,19 @@
@Component
class ApiJwtAuthenticationFilter : OncePerRequestFilter() {
- @Autowired
- lateinit var jwtConfig: JwtConfig
- @Autowired
- lateinit var apiJwtRepository: ApiJwtRepository
-
- private var jwtUtil: JwtTokenUtil? = null
-
- private fun getUtil(): JwtTokenUtil {
- if (jwtUtil == null) {
- jwtUtil = JwtTokenUtil((jwtConfig))
- }
- return jwtUtil as JwtTokenUtil
- }
+ @Resource(name = "jwtRequestData")
+ private lateinit var jwtRequestData: JwtRequestData
override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) {
- request.getHeader(jwtConfig.header)?.let { authHeader ->
+ jwtRequestData.jwtToken?.let { jwt ->
try {
- val jwt = if (authHeader.startsWith(jwtConfig.tokenHeader)) {
- authHeader.substring(jwtConfig.tokenHeader.length)
- } else {
- throw JoseException("JWT Header error")
- }
- val claims = getUtil().verifyToken(jwt)
- apiJwtRepository.findById(claims[ReservedClaimNames.JWT_ID].toString()).let {
- if (!it.isPresent) {
- throw JoseException("JWT has not been register")
- }
- // token 已被设为黑名单
- if (it.get().status != TradeDict.JWT_STATUS_NORMAL) {
- throw JoseException("JWT status error : ${it.get().status}")
- }
- }
- if (jwtConfig.multiTenant) {
- val tenantId = request.getHeader(Constants.HEADER_TETANTID)
- if (tenantId == null) {
- response.status = HttpStatus.UNAUTHORIZED.value()
- return
- }
- if (claims[Constants.JWT_CLAIM_TENANTID] != tenantId) {
- response.status = HttpStatus.UNAUTHORIZED.value()
- return
- }
- }
- val auth = UsernamePasswordAuthenticationToken(claims[Constants.JWT_CLAIM_UID], null,
- (claims[Constants.JWT_CLAIM_AUTHORITIES] as ArrayList<*>)
+ val auth = UsernamePasswordAuthenticationToken(jwt.uid, null,
+ (jwt.authorities as ArrayList<*>)
.map { SimpleGrantedAuthority(it as String) })
SecurityContextHolder.getContext().authentication = auth
} catch (e: InvalidJwtException) {
SecurityContextHolder.clearContext()
- if (e.hasExpired()) {
- // jwt 过期后返回 401
- apiJwtRepository.deleteById(e.jwtContext.jwtClaims.jwtId)
- }
response.status = HttpStatus.UNAUTHORIZED.value()
return
} catch (e: JoseException) {
@@ -126,20 +81,9 @@
@Component
class MobileSecurityFilter : OncePerRequestFilter() {
- @Autowired
- lateinit var jwtConfig: JwtConfig
- @Autowired
- lateinit var apiJwtRepository: ApiJwtRepository
-
- private var jwtUtil: JwtTokenUtil? = null
-
- private fun getUtil(): JwtTokenUtil {
- if (jwtUtil == null) {
- jwtUtil = JwtTokenUtil((jwtConfig))
- }
- return jwtUtil as JwtTokenUtil
- }
+ @Resource(name = "jwtRequestData")
+ private lateinit var jwtRequestData: JwtRequestData
override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) {
var context: String? = request.contextPath
@@ -159,44 +103,14 @@
filterChain.doFilter(request, response)
return
}
- request.getHeader(jwtConfig.header)?.let { authHeader ->
+ jwtRequestData.jwtToken?.let { jwt ->
try {
- val jwt = if (authHeader.startsWith(jwtConfig.tokenHeader)) {
- authHeader.substring(jwtConfig.tokenHeader.length)
- } else {
- throw JoseException("JWT Header error")
- }
- val claims = getUtil().verifyToken(jwt)
- apiJwtRepository.findById(claims[ReservedClaimNames.JWT_ID].toString()).let {
- if (!it.isPresent) {
- throw JoseException("JWT has not been register")
- }
- // token 已被设为黑名单
- if (it.get().status != TradeDict.JWT_STATUS_NORMAL) {
- throw JoseException("JWT status error : ${it.get().status}")
- }
- }
- if (jwtConfig.multiTenant) {
- val tenantId = request.getHeader(Constants.HEADER_TETANTID)
- if (tenantId == null) {
- response.status = HttpStatus.UNAUTHORIZED.value()
- return
- }
- if (claims[Constants.JWT_CLAIM_TENANTID] != tenantId) {
- response.status = HttpStatus.UNAUTHORIZED.value()
- return
- }
- }
- val auth = UsernamePasswordAuthenticationToken(claims[Constants.JWT_CLAIM_UID], null,
- (claims[Constants.JWT_CLAIM_AUTHORITIES] as ArrayList<*>)
+ val auth = UsernamePasswordAuthenticationToken(jwt.uid, null,
+ (jwt.authorities as ArrayList<*>)
.map { SimpleGrantedAuthority(it as String) })
SecurityContextHolder.getContext().authentication = auth
} catch (e: InvalidJwtException) {
SecurityContextHolder.clearContext()
- if (e.hasExpired()) {
- // jwt 过期后返回 401
- apiJwtRepository.deleteById(e.jwtContext.jwtClaims.jwtId)
- }
response.status = HttpStatus.UNAUTHORIZED.value()
return
} catch (e: JoseException) {
@@ -373,6 +287,11 @@
// 设置 Web MVC 应用权限
http.apply(validateCodeSecurityConfig)
.and()
+ .headers { headers ->
+ headers.xssProtection { xssProtection ->
+ xssProtection.xssProtectionEnabled(true)
+ }
+ }
.authorizeRequests()
.antMatchers("/login", "/login/form", "/mobileapi/**", "/userinfor").permitAll()
.antMatchers("/static/**").permitAll()
@@ -395,6 +314,7 @@
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.and().csrf().ignoringAntMatchers("oauth/**")
+
// 设置 Web MVC 应用权限
// http.apply(validateCodeSecurityConfig)
// .and()
diff --git a/payapi/src/main/resources/application.properties b/payapi/src/main/resources/application.properties
index 906a5be..377a873 100644
--- a/payapi/src/main/resources/application.properties
+++ b/payapi/src/main/resources/application.properties
@@ -32,8 +32,8 @@
## quartz task scheduler
shopbalance.updater.cron=*/10 * * * * ?
dayend.settletask.cron=0 3/30 2-3 * * ?
-query.third.transdtl.result.cron=7 0/1 * * * ?
-payapi.sourcetype.checker.scheduler=7 3/10 * * * ?
+query.third.transdtl.result.cron=-
+payapi.sourcetype.checker.scheduler=-
citizencard.dolosstask.cron=-
################################################
# user password
diff --git a/payapi/src/test/kotlin/com/supwisdom/dlpay/controller/security_controller_test.kt b/payapi/src/test/kotlin/com/supwisdom/dlpay/controller/security_controller_test.kt
index 24853db..65bd05b 100644
--- a/payapi/src/test/kotlin/com/supwisdom/dlpay/controller/security_controller_test.kt
+++ b/payapi/src/test/kotlin/com/supwisdom/dlpay/controller/security_controller_test.kt
@@ -1,8 +1,8 @@
package com.supwisdom.dlpay.controller
import com.supwisdom.dlpay.MvcBaseTest
-import com.supwisdom.dlpay.framework.core.JwtConfig
import com.supwisdom.dlpay.framework.util.HmacUtil
+import com.supwisdom.multitenant.jwt.config.JwtProperties
import io.restassured.RestAssured
import io.restassured.RestAssured.*
import io.restassured.http.ContentType
@@ -28,7 +28,7 @@
private var port: Int = 0
@Autowired
- lateinit var jwtConfig: JwtConfig
+ private lateinit var jwtProperties: JwtProperties
@Before
fun setUp() {
@@ -96,7 +96,7 @@
@Test
fun testJwtRefresh() {
getJwt(appid, appsecret).also { jwt ->
- given().header(jwtConfig.header, "${jwtConfig.tokenHeader}$jwt")
+ given().header(jwtProperties.jwtHeader, "${jwtProperties.schema} $jwt")
.`when`()
.get("/api/auth/refresh")
.then()