实现了 jwt authentication
diff --git a/build.gradle b/build.gradle
index c273d3c..6823062 100644
--- a/build.gradle
+++ b/build.gradle
@@ -26,6 +26,7 @@
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
+ implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.security:spring-security-oauth2-client'
@@ -47,6 +48,8 @@
implementation files('libs/ojdbc6.jar')
+ annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
+
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
diff --git a/config/application-devel-oracle.properties b/config/application-devel-oracle.properties
index fbfa731..3a3d0a6 100644
--- a/config/application-devel-oracle.properties
+++ b/config/application-devel-oracle.properties
@@ -7,4 +7,10 @@
spring.datasource.url=jdbc:oracle:thin:@172.28.201.101:47922:orcl
spring.datasource.username=ecardtest
spring.datasource.password=kingstar
-spring.datasource.driver-class-oracle.jdbc.driver.OracleDriver
\ No newline at end of file
+spring.datasource.driver-class-oracle.jdbc.driver.OracleDriver
+
+# Redis settings
+redis.server=172.28.201.101
+redis.port=16379
+redis.password=kingstar
+redis.database=0
\ No newline at end of file
diff --git a/config/application-devel-pg-local.properties b/config/application-devel-pg-local.properties
new file mode 100644
index 0000000..39d4caf
--- /dev/null
+++ b/config/application-devel-pg-local.properties
@@ -0,0 +1,19 @@
+spring.main.banner-mode=off
+# create and drop tables and sequences, loads import.sql
+spring.jpa.hibernate.ddl-auto=update
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
+spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false
+# Postgresql settings
+spring.datasource.url=jdbc:postgresql://localhost:5432/payapi
+spring.datasource.username=payapi
+spring.datasource.password=123456
+# Redis settings
+redis.server=localhost
+redis.port=6379
+redis.password=
+redis.database=0
+# jwt settings
+jwt.secret=Zj5taLomEbrM0lk+NMQZbHfSxaDU1wekjT+kiC3YzDw=
+# timeout seconds
+jwt.expiration=3600
+jwt.header=payapi
diff --git a/config/application-devel-pg.properties b/config/application-devel-pg.properties
index 64f9736..92b7ecf 100644
--- a/config/application-devel-pg.properties
+++ b/config/application-devel-pg.properties
@@ -1,11 +1,19 @@
spring.main.banner-mode=off
-
# create and drop tables and sequences, loads import.sql
-spring.jpa.hibernate.ddl-auto=create-drop
-spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
-spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
-
-# Oracle settings
+spring.jpa.hibernate.ddl-auto=update
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
+spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false
+# Postgresql settings
spring.datasource.url=jdbc:postgresql://172.28.201.70:15432/payapi
spring.datasource.username=payapi
spring.datasource.password=123456
+# Redis settings
+redis.server=172.28.201.101
+redis.port=16379
+redis.password=kingstar
+redis.database=0
+# jwt settings
+jwt.secret=Zj5taLomEbrM0lk+NMQZbHfSxaDU1wekjT+kiC3YzDw=
+# timeout seconds
+jwt.expiration=3600
+jwt.header=payapi
diff --git a/sql/init_test.sql b/sql/init_test.sql
new file mode 100644
index 0000000..d4396a6
--- /dev/null
+++ b/sql/init_test.sql
@@ -0,0 +1,4 @@
+insert into tt_apiclient(appid, secret, status)
+values ('100001', 'oUw2NmA09ficiVWD4TUQLDOkPyzQa3VzbjjsW0B2qTk=', 'normal');
+
+commit;
\ No newline at end of file
diff --git a/src/main/java/com/supwisdom/dlpay/framework/core/JwtTokenUtil.java b/src/main/java/com/supwisdom/dlpay/framework/core/JwtTokenUtil.java
new file mode 100644
index 0000000..e43e411
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/framework/core/JwtTokenUtil.java
@@ -0,0 +1,59 @@
+package com.supwisdom.dlpay.framework.core;
+
+import org.jose4j.jwk.JsonWebKey;
+import org.jose4j.jws.AlgorithmIdentifiers;
+import org.jose4j.jws.JsonWebSignature;
+import org.jose4j.jwt.JwtClaims;
+import org.jose4j.lang.JoseException;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Configuration
+@EnableAutoConfiguration
+@Component
+public class JwtTokenUtil {
+ @Value("${jwt.secret}")
+ private String secret;
+ @Value("${jwt.expiration}")
+ private Long expiration = 3600L;
+ @Value("${jwt.header}")
+ private String header = "supwisdom";
+
+ public String generateToken(Map<String, Object> params) throws JoseException {
+ JwtClaims claims = new JwtClaims();
+ claims.setIssuer(params.get("issuer").toString()); // who creates the token and signs it
+ claims.setExpirationTimeMinutesInTheFuture(expiration / 60); // time when the token will expire (10 minutes from now)
+ claims.setGeneratedJwtId(); // a unique identifier for the token
+ claims.setIssuedAtToNow(); // when the token was issued/created (now)
+ claims.setNotBeforeMinutesInThePast(2); // time before which the token is not yet valid (2 minutes ago)
+ claims.setSubject(params.get("subject").toString()); // the subject/principal is whom the token is about
+ /*
+ 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", secret);
+ 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 jws.getCompactSerialization();
+ }
+
+ public String generateToken(UserDetails userDetails) throws JoseException {
+ Map<String, Object> claims = new HashMap<>();
+ claims.put("uid", userDetails.getUsername());
+ return generateToken(claims);
+ }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/dao/ApiClientDao.java b/src/main/java/com/supwisdom/dlpay/framework/dao/ApiClientDao.java
new file mode 100644
index 0000000..4390368
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/framework/dao/ApiClientDao.java
@@ -0,0 +1,7 @@
+package com.supwisdom.dlpay.framework.dao;
+
+import com.supwisdom.dlpay.framework.domain.TApiClient;
+import org.springframework.data.repository.CrudRepository;
+
+public interface ApiClientDao extends CrudRepository<TApiClient, String> {
+}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/domain/AppClientRedis.java b/src/main/java/com/supwisdom/dlpay/framework/domain/AppClientRedis.java
new file mode 100644
index 0000000..a45f9f3
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/framework/domain/AppClientRedis.java
@@ -0,0 +1,39 @@
+package com.supwisdom.dlpay.framework.domain;
+
+import org.springframework.data.redis.core.RedisHash;
+
+import javax.persistence.Id;
+
+@RedisHash("app_client")
+public class AppClientRedis {
+ private @Id
+ String id;
+
+ String token;
+
+ String loginTimestamp;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+
+ public String getLoginTimestamp() {
+ return loginTimestamp;
+ }
+
+ public void setLoginTimestamp(String loginTimestamp) {
+ this.loginTimestamp = loginTimestamp;
+ }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/domain/DateItem.java b/src/main/java/com/supwisdom/dlpay/framework/domain/DateItem.java
new file mode 100644
index 0000000..f4aa56e
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/framework/domain/DateItem.java
@@ -0,0 +1,26 @@
+package com.supwisdom.dlpay.framework.domain;
+
+import javax.persistence.*;
+import java.sql.Date;
+
+@Entity
+public class DateItem {
+ private Date date;
+
+ /**
+ * @return the date
+ */
+ @Id
+ @Column(name = "DATE_VALUE")
+ public Date getDate() {
+ return date;
+ }
+
+ /**
+ * @param date
+ * the date to set
+ */
+ public void setDate(Date date) {
+ this.date = date;
+ }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/domain/PersonRedis.java b/src/main/java/com/supwisdom/dlpay/framework/domain/PersonRedis.java
new file mode 100644
index 0000000..2c25864
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/framework/domain/PersonRedis.java
@@ -0,0 +1,59 @@
+package com.supwisdom.dlpay.framework.domain;
+
+import org.springframework.data.redis.core.RedisHash;
+
+import javax.persistence.Id;
+
+@RedisHash("person")
+public class PersonRedis {
+ @Id
+ String id;
+
+ String loginTimestamp;
+
+ String roles;
+
+ Boolean isAdmin;
+
+ String accessToken;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getLoginTimestamp() {
+ return loginTimestamp;
+ }
+
+ public void setLoginTimestamp(String loginTimestamp) {
+ this.loginTimestamp = loginTimestamp;
+ }
+
+ public String getRoles() {
+ return roles;
+ }
+
+ public void setRoles(String roles) {
+ this.roles = roles;
+ }
+
+ public Boolean getAdmin() {
+ return isAdmin;
+ }
+
+ public void setAdmin(Boolean admin) {
+ isAdmin = admin;
+ }
+
+ public String getAccessToken() {
+ return accessToken;
+ }
+
+ public void setAccessToken(String accessToken) {
+ this.accessToken = accessToken;
+ }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/domain/TApiClient.java b/src/main/java/com/supwisdom/dlpay/framework/domain/TApiClient.java
new file mode 100644
index 0000000..5f19465
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/framework/domain/TApiClient.java
@@ -0,0 +1,44 @@
+package com.supwisdom.dlpay.framework.domain;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "TT_APICLIENT")
+public class TApiClient {
+ @Id
+ @Column(name = "appid", nullable = false, length = 20)
+ private String appid;
+
+ @Column(name = "secret", nullable = false, length = 64)
+ private String secret;
+
+ @Column(name = "status", nullable = false, length = 10)
+ private String status;
+
+ public String getAppid() {
+ return appid;
+ }
+
+ public void setAppid(String appid) {
+ this.appid = appid;
+ }
+
+ public String getSecret() {
+ return secret;
+ }
+
+ public void setSecret(String secret) {
+ this.secret = secret;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/redisrepo/AppClientRepository.java b/src/main/java/com/supwisdom/dlpay/framework/redisrepo/AppClientRepository.java
new file mode 100644
index 0000000..495a122
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/framework/redisrepo/AppClientRepository.java
@@ -0,0 +1,7 @@
+package com.supwisdom.dlpay.framework.redisrepo;
+
+import com.supwisdom.dlpay.framework.domain.AppClientRedis;
+import org.springframework.data.repository.CrudRepository;
+
+public interface AppClientRepository extends CrudRepository<AppClientRedis, String> {
+}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/redisrepo/PersonRepository.java b/src/main/java/com/supwisdom/dlpay/framework/redisrepo/PersonRepository.java
new file mode 100644
index 0000000..a4925cd
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/framework/redisrepo/PersonRepository.java
@@ -0,0 +1,7 @@
+package com.supwisdom.dlpay.framework.redisrepo;
+
+import com.supwisdom.dlpay.framework.domain.PersonRedis;
+import org.springframework.data.repository.CrudRepository;
+
+public interface PersonRepository extends CrudRepository<PersonRedis, String> {
+}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/service/impl/SystemUtilServiceImpl.java b/src/main/java/com/supwisdom/dlpay/framework/service/impl/SystemUtilServiceImpl.java
index b4b8b48..0cf7bcf 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/service/impl/SystemUtilServiceImpl.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/service/impl/SystemUtilServiceImpl.java
@@ -4,6 +4,7 @@
import com.supwisdom.dlpay.framework.dao.TaskLockDao;
import com.supwisdom.dlpay.framework.dao.TranscodeDao;
import com.supwisdom.dlpay.framework.data.SystemDateTime;
+import com.supwisdom.dlpay.framework.domain.DateItem;
import com.supwisdom.dlpay.framework.domain.TSettlectl;
import com.supwisdom.dlpay.framework.domain.TTaskLock;
import com.supwisdom.dlpay.framework.domain.TTranscode;
@@ -14,8 +15,19 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+import javax.persistence.criteria.CriteriaBuilder;
+import java.sql.SQLException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
@Service
public class SystemUtilServiceImpl implements SystemUtilService {
+ @PersistenceContext
+ EntityManager em;
+
@Autowired
private TaskLockDao taskLockDao;
@Autowired
@@ -25,11 +37,45 @@
private static final Logger logger = Logger.getLogger(SystemUtilServiceImpl.class);
+ public static class SystemDateTimeImpl implements SystemDateTime {
+ private Date now;
+ private static final SimpleDateFormat sdft = new SimpleDateFormat("yyyyMMddHHmmss");
+
+ public SystemDateTimeImpl(Date now) {
+ this.now = now;
+ }
+
+ @Override
+ public String getHostdate() {
+ return sdft.format(this.now).substring(0, 8);
+ }
+
+ @Override
+ public String getHosttime() {
+ return sdft.format(this.now).substring(8, 14);
+ }
+
+ @Override
+ public String getHostdatetime() {
+ return sdft.format(this.now);
+ }
+
+ @Override
+ public Date getSysdate() {
+ return this.now;
+ }
+ }
+
/**
* 获取oracle数据库时间
*/
private SystemDateTime getOracleDatetime() {
- return taskLockDao.getOracleDatetime();
+// return taskLockDao.getOracleDatetime();
+ String sql = "SELECT CURRENT_TIMESTAMP AS DATE_VALUE";
+ Query query = em.createNativeQuery(sql, DateItem.class);
+ DateItem dateItem = (DateItem) query.getSingleResult();
+ SystemDateTime now = new SystemDateTimeImpl(dateItem.getDate());
+ return now;
}
@Override
@@ -38,7 +84,7 @@
}
@Override
- public TTaskLock updateTaskLock(TTaskLock lock){
+ public TTaskLock updateTaskLock(TTaskLock lock) {
return taskLockDao.save(lock);
}
@@ -80,12 +126,12 @@
return hostdate;
}
- private String getOracleRefno(){
- return taskLockDao.getOracleRefno();
+ private String getOracleRefno() {
+ return taskLockDao.getOracleRefno();
}
@Override
- public String getRefno(){
+ public String getRefno() {
return getOracleRefno();
}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/util/HmacUtil.java b/src/main/java/com/supwisdom/dlpay/framework/util/HmacUtil.java
index 0978e28..8e4e55d 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/util/HmacUtil.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/util/HmacUtil.java
@@ -3,126 +3,141 @@
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
public class HmacUtil {
- /**
- * 除去数组中的空值和签名参数
- *
- * @param sArray 签名参数组
- * @return 去掉空值与签名参数后的新签名参数组
- */
- public static Map<String, String> paraFilter(Map<String, String> sArray) {
+ /**
+ * 除去数组中的空值和签名参数
+ *
+ * @param sArray 签名参数组
+ * @return 去掉空值与签名参数后的新签名参数组
+ */
+ public static Map<String, String> paraFilter(Map<String, String> sArray) {
- Map<String, String> result = new HashMap<String, String>();
+ Map<String, String> result = new HashMap<String, String>();
- if (sArray == null || sArray.size() <= 0) {
- return result;
- }
-
- for (String key : sArray.keySet()) {
- String value = sArray.get(key);
- if (value == null || value.equals("") || "null".equals(value) || key.equalsIgnoreCase("sign")) {
- continue;
- }
- result.put(key, value);
- }
-
- return result;
+ if (sArray == null || sArray.size() <= 0) {
+ return result;
}
- /**
- * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
- *
- * @param params 需要排序并参与字符拼接的参数组
- * @return 拼接后字符串
- */
- public static String createLinkString(Map<String, String> params) {
-
- List<String> keys = new ArrayList<String>(params.keySet());
- Collections.sort(keys);
-
- String prestr = "";
-
- for (int i = 0; i < keys.size(); i++) {
- String key = keys.get(i);
- String value = params.get(key);
-
- if (i == keys.size() - 1) {//拼接时,不包括最后一个&字符
- prestr = prestr + key + "=" + value;
- } else {
- prestr = prestr + key + "=" + value + "&";
- }
- }
-
- return prestr;
+ for (String key : sArray.keySet()) {
+ String value = sArray.get(key);
+ if (value == null || value.equals("") || "null".equals(value) || key.equalsIgnoreCase("sign")) {
+ continue;
+ }
+ result.put(key, value);
}
- public static String HMACSHA1(String data, String key) {
- byte[] byteHMAC = null;
- try {
- Mac mac = Mac.getInstance("HmacSHA1");
- SecretKeySpec spec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
- mac.init(spec);
- byteHMAC = mac.doFinal(data.getBytes("UTF-8"));
- } catch (InvalidKeyException e) {
- e.printStackTrace();
- } catch (NoSuchAlgorithmException ignore) {
- ignore.printStackTrace();
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
+ return result;
+ }
- if (byteHMAC != null) {
- try {
- String hexMac = getHexString(byteHMAC);
- return hexMac;
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return null;
- }
- return null;
+ /**
+ * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
+ *
+ * @param params 需要排序并参与字符拼接的参数组
+ * @return 拼接后字符串
+ */
+ public static String createLinkString(Map<String, String> params) {
+ List<String> keys = new ArrayList<String>(params.keySet());
+ Collections.sort(keys);
+
+ String prestr = "";
+
+ for (int i = 0; i < keys.size(); i++) {
+ String key = keys.get(i);
+ String value = params.get(key);
+
+ if (i == keys.size() - 1) {//拼接时,不包括最后一个&字符
+ prestr = prestr + key + "=" + value;
+ } else {
+ prestr = prestr + key + "=" + value + "&";
+ }
}
- public static String getHexString(byte[] b) throws Exception {
- String result = "";
- for (int i = 0; i < b.length; i++) {
- result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
- }
- return result;
+ return prestr;
+ }
+
+ private static String HMACSHAX(String data, String key, String alg) {
+ String algorithm = "";
+ if ("SHA1".equals(alg)) {
+ algorithm = "HmacSHA1";
+ } else if ("SHA256".equals(alg)) {
+ algorithm = "HmacSHA256";
+ } else if ("SHA512".equals(alg)) {
+ algorithm = "HmacSHA512";
+ }
+ byte[] byteHMAC = null;
+ try {
+ Mac mac = Mac.getInstance(algorithm);
+ SecretKeySpec spec = new SecretKeySpec(key.getBytes(), algorithm);
+ mac.init(spec);
+ byteHMAC = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
+ } catch (InvalidKeyException | NoSuchAlgorithmException e) {
+ e.printStackTrace();
}
- public static boolean checkHmacSign(String data, String key, String sign) {
- String asign = HMACSHA1(data, key);
- if (asign == null) {
- return false;
- }
- if (asign.equalsIgnoreCase(sign)) {
- return true;
- }
+ if (byteHMAC != null) {
+ try {
+ String hexMac = getHexString(byteHMAC);
+ return hexMac;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+ return null;
+ }
- return false;
+ public static String HMACSHA256(String data, String key) {
+ return HMACSHAX(data, key, "SHA256");
+ }
+
+ public static String HMACSHA512(String data, String key) {
+ return HMACSHAX(data, key, "SHA512");
+ }
+
+ public static String HMACSHA1(String data, String key) {
+ return HMACSHAX(data, key, "SHA1");
+ }
+
+ public static String getHexString(byte[] b) throws Exception {
+ String result = "";
+ for (int i = 0; i < b.length; i++) {
+ result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
+ }
+ return result;
+ }
+
+ public static boolean checkHmacSign(String data, String key, String sign) {
+ String asign = HMACSHA1(data, key);
+ if (asign == null) {
+ return false;
+ }
+ if (asign.equalsIgnoreCase(sign)) {
+ return true;
}
- public static void main(String[] args) {
- String refno = DateUtil.getNow();
- Map<String, String> mapValue = new HashMap<String, String>();
- mapValue.put("tradeaccount", "10000097");
- mapValue.put("tradename", "在线点餐");
- mapValue.put("tradeamount", "1");
- mapValue.put("paidamount", "1");
- mapValue.put("outtradeno", refno);
- mapValue.put("yktshopid", "2");
- mapValue.put("shopid", "68512084");
- String signstr = createLinkString(HmacUtil.paraFilter(mapValue));
- String sign = HmacUtil.HMACSHA1(signstr, "adc4ac6822fd462780f878b86cb94688");
- System.out.println("{\"tradeaccount\":\"10000097\",\"tradename\":\"在线点餐\",\"tradeamount\":\"1\"," +
- "\"paidamount\": \"1\",\"outtradeno\":\""+refno+"\",\"yktshopid\": \"2\",\"shopid\":\"68512084\",\"sign\": \""+sign+"\"}");
- }
+ return false;
+ }
+
+ public static void main(String[] args) {
+ String refno = DateUtil.getNow();
+ Map<String, String> mapValue = new HashMap<String, String>();
+ mapValue.put("tradeaccount", "10000097");
+ mapValue.put("tradename", "在线点餐");
+ mapValue.put("tradeamount", "1");
+ mapValue.put("paidamount", "1");
+ mapValue.put("outtradeno", refno);
+ mapValue.put("yktshopid", "2");
+ mapValue.put("shopid", "68512084");
+ String signstr = createLinkString(HmacUtil.paraFilter(mapValue));
+ String sign = HmacUtil.HMACSHA1(signstr, "adc4ac6822fd462780f878b86cb94688");
+ System.out.println("{\"tradeaccount\":\"10000097\",\"tradename\":\"在线点餐\",\"tradeamount\":\"1\"," +
+ "\"paidamount\": \"1\",\"outtradeno\":\"" + refno + "\",\"yktshopid\": \"2\",\"shopid\":\"68512084\",\"sign\": \"" + sign + "\"}");
+ }
}
diff --git a/src/main/kotlin/com/supwisdom/dlpay/DlpayApplication.kt b/src/main/kotlin/com/supwisdom/dlpay/DlpayApplication.kt
index baa9e6c..68a0e61 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/DlpayApplication.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/DlpayApplication.kt
@@ -1,35 +1,63 @@
package com.supwisdom.dlpay
-import org.springframework.beans.factory.annotation.Autowired
+import io.lettuce.core.ReadFrom
+import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.context.annotation.Bean
-import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
-import org.springframework.context.annotation.PropertySource
import org.springframework.core.annotation.Order
-import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
+import org.springframework.data.redis.connection.RedisConnectionFactory
+import org.springframework.data.redis.connection.RedisPassword
+import org.springframework.data.redis.connection.RedisStandaloneConfiguration
+import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration
+import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory
+import org.springframework.data.redis.core.RedisKeyValueTemplate
+import org.springframework.data.redis.core.RedisTemplate
+import org.springframework.data.redis.repository.configuration.EnableRedisRepositories
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.WebSecurityConfigurerAdapter
import org.springframework.security.config.http.SessionCreationPolicy
-import org.springframework.security.core.Authentication
import org.springframework.security.core.userdetails.User
import org.springframework.security.core.userdetails.UserDetailsService
-import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository
import org.springframework.security.provisioning.InMemoryUserDetailsManager
import org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler
-import org.springframework.security.web.authentication.logout.LogoutSuccessHandler
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
-import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer
-import javax.servlet.http.HttpServletRequest
-import javax.servlet.http.HttpServletResponse
+@Configuration
+@EnableRedisRepositories
+class AppConfig {
+
+ @Value("\${redis.server}")
+ lateinit var server: String
+
+ @Value("\${redis.port}")
+ var port: Int = 0
+
+ @Value("\${redis.database}")
+ var database: Int = 0
+
+ @Value("\${redis.password}")
+ lateinit var password: String
+
+ @Bean
+ fun redisConnectionFactory(): RedisConnectionFactory {
+ val clientConfig = LettuceClientConfiguration.builder()
+ .readFrom(ReadFrom.SLAVE_PREFERRED)
+ .build()
+ val serverConfig = RedisStandaloneConfiguration(server, port)
+ if (!password.isNullOrEmpty()) {
+ serverConfig.password = RedisPassword.of(password)
+ }
+ serverConfig.database = database
+
+ return LettuceConnectionFactory(serverConfig, clientConfig)
+ }
+}
+
@EnableWebSecurity
class WebSecurityConfig {
- @Autowired
- private lateinit var clientRegistrationRepository: ClientRegistrationRepository
@Bean
fun userDetailsService(): UserDetailsService {
@@ -45,8 +73,8 @@
@Configuration
@Order(1)
class ApiWebSecurityConfigurationAdapter : WebSecurityConfigurerAdapter() {
- @Autowired
- private lateinit var clientRegistrationRepository: ClientRegistrationRepository
+// @Autowired
+// private lateinit var clientRegistrationRepository: ClientRegistrationRepository
override fun configure(http: HttpSecurity) {
http.authorizeRequests()
diff --git a/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt b/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt
new file mode 100644
index 0000000..465e74f
--- /dev/null
+++ b/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt
@@ -0,0 +1,91 @@
+package com.supwisdom.dlpay.framework.controller
+
+import com.supwisdom.dlpay.framework.ResponseBodyBuilder
+import com.supwisdom.dlpay.framework.core.JwtTokenUtil
+import com.supwisdom.dlpay.framework.dao.ApiClientDao
+import com.supwisdom.dlpay.framework.domain.AppClientRedis
+import com.supwisdom.dlpay.framework.redisrepo.AppClientRepository
+import com.supwisdom.dlpay.framework.service.SystemUtilService
+import com.supwisdom.dlpay.framework.util.HmacUtil
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.ResponseEntity
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+import java.util.*
+
+@RestController
+@RequestMapping("/auth")
+class ApiAuthController {
+
+ @Autowired
+ lateinit var repo: AppClientRepository
+
+ @Autowired
+ lateinit var apiClient: ApiClientDao
+
+ @Autowired
+ lateinit var systemUtil: SystemUtilService
+
+ @Autowired
+ lateinit var jwtUtil: JwtTokenUtil
+
+ @GetMapping("/gettoken")
+ fun loginInit(appid: String): ResponseEntity<Any> {
+ apiClient.findById(appid).run {
+ if (!isPresent) {
+ return ResponseEntity.status(401).build()
+ }
+ if (get().status != "normal") {
+ return ResponseEntity.ok(ResponseBodyBuilder.create()
+ .fail(1, "API状态错误"))
+ }
+ get()
+ }.let {
+ val token = generateRandomToken()
+ val now = systemUtil.sysdatetime.hostdatetime
+ AppClientRedis().apply {
+ id = appid
+ loginTimestamp = now
+ this.token = HmacUtil.HMACSHA256(token, it.secret)
+ }.also {
+ repo.save(it)
+ }
+ return ResponseEntity.ok(ResponseBodyBuilder.create()
+ .data("token", token)
+ .data("timestamp", now)
+ .success())
+ }
+ }
+
+ private fun generateRandomToken(): String {
+ val random = ByteArray(12) { 0x00 }
+ Random(System.currentTimeMillis()).nextBytes(random)
+ return Base64.getEncoder().encode(random).toString(Charsets.UTF_8)
+ }
+
+ private fun checkSecretToken(app: AppClientRedis, secret: String): Boolean {
+ return (app.token == secret)
+ }
+
+ @GetMapping("/authentication")
+ fun login(appid: String, secret: String): ResponseEntity<Any> {
+ return repo.findById(appid).let {
+ if (it.isPresent && checkSecretToken(it.get(), secret)) {
+ it.get().also { client ->
+ client.token = ""
+ repo.save(client)
+ }
+ val token = jwtUtil.generateToken(
+ mapOf("uid" to appid, "issuer" to "supwisdom",
+ "subject" to "payapi"))
+ ResponseEntity.ok(ResponseBodyBuilder.create()
+ .data("jwt", token)
+ .data("appid", appid)
+ .success())
+ } else {
+ ResponseEntity.status(401).build()
+ }
+ }
+ }
+}
\ No newline at end of file