Browse Source

新增:

1.获取open-api accessToken
dev_shibei_match
wxz 4 years ago
parent
commit
155344781f
  1. 26
      epmet-commons/epmet-commons-security/pom.xml
  2. 112
      epmet-commons/epmet-commons-security/src/main/java/com/epmet/commons/security/jwt/JwtTokenUtils.java
  3. 76
      epmet-commons/epmet-commons-security/src/main/java/com/epmet/commons/security/sign/openapi/OpenApiSignUtils.java
  4. 5
      epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/exception/EpmetErrorCode.java
  5. 10
      epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/redis/RedisKeys.java
  6. 40
      epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/utils/ConvertUtils.java
  7. 3
      epmet-commons/pom.xml
  8. 19
      epmet-module/epmet-ext/epmet-ext-client/src/main/java/com/epmet/dto/form/AccessTokenFormDTO.java
  9. 10
      epmet-module/epmet-ext/epmet-ext-server/pom.xml
  10. 15
      epmet-module/epmet-ext/epmet-ext-server/src/main/java/com/epmet/config/OpenApiConfig.java
  11. 88
      epmet-module/epmet-ext/epmet-ext-server/src/main/java/com/epmet/controller/OpenApiAccessTokenController.java
  12. 15
      epmet-module/epmet-ext/epmet-ext-server/src/main/java/com/epmet/service/OpenApiAccessTokenService.java
  13. 44
      epmet-module/epmet-ext/epmet-ext-server/src/main/java/com/epmet/service/impl/OpenApiAccessTokenServiceImpl.java
  14. 5
      epmet-module/epmet-ext/epmet-ext-server/src/main/resources/bootstrap.yml

26
epmet-commons/epmet-commons-security/pom.xml

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>epmet-commons</artifactId>
<groupId>com.epmet</groupId>
<version>2.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>epmet-commons-security</artifactId>
<dependencies>
<dependency>
<groupId>com.epmet</groupId>
<artifactId>epmet-commons-tools</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
</dependencies>
</project>

112
epmet-commons/epmet-commons-security/src/main/java/com/epmet/commons/security/jwt/JwtTokenUtils.java

@ -0,0 +1,112 @@
/**
* Copyright (c) 2018 人人开源 All rights reserved.
* <p>
* https://www.renren.io
* <p>
* 版权所有侵权必究
*/
package com.epmet.commons.security.jwt;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* Jwt工具类
*
* @author Mark sunlightcs@gmail.com
* @since 1.0.0
*/
@Component
public class JwtTokenUtils {
private static final Logger logger = LoggerFactory.getLogger(JwtTokenUtils.class);
public Claims getClaimByToken(String token, String secret) {
try {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
} catch (Exception e) {
logger.debug("validate is token error, token = " + token, e);
return null;
}
}
/**
* @return java.util.Date
* @param token
* @Author yinzuomei
* @Description 获取token的有效期截止时间
* @Date 2020/3/18 22:17
**/
public Date getExpiration(String token, String secret){
try {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody().getExpiration();
} catch (Exception e) {
logger.debug("validate is token error, token = " + token, e);
return null;
}
}
/**
* @return java.lang.String
* @Author yinzuomei
* @Description 根据app+client+userId生成token
* @Date 2020/3/18 22:29
**/
public String createToken(Map<String, Object> claims, int expire, String secret) {
return Jwts.builder()
.setHeaderParam("typ", "JWT")
.setClaims(claims)
.setIssuedAt(new Date())
.setExpiration(DateTime.now().plusSeconds(expire).toDate())
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
/**
* token是否过期
*
* @return true过期
*/
public boolean isTokenExpired(Date expiration) {
return expiration.before(new Date());
}
public static void main(String[] args) {
Map<String, Object> map=new HashMap<>();
map.put("app","gov");
map.put("client","wxmp");
map.put("userId","100526ABC");
String tokenStr=Jwts.builder()
.setHeaderParam("typ", "JWT")
.setClaims(map)
.setIssuedAt(new Date())
.setExpiration(DateTime.now().plusSeconds(604800).toDate())
.signWith(SignatureAlgorithm.HS512, "7016867071f0ebf1c46f123eaaf4b9d6[elink.epmet]")
.compact();
System.out.println(tokenStr);
Claims claims= Jwts.parser()
.setSigningKey("7016867071f0ebf1c46f123eaaf4b9d6[elink.epmet]")
.parseClaimsJws(tokenStr)
.getBody();
System.out.println("app="+ claims.get("app"));
System.out.println("client="+ claims.get("client"));
System.out.println("userId="+ claims.get("userId"));
}
}

76
epmet-commons/epmet-commons-security/src/main/java/com/epmet/commons/security/sign/openapi/OpenApiSignUtils.java

@ -0,0 +1,76 @@
package com.epmet.commons.security.sign.openapi;
import com.epmet.commons.tools.utils.Md5Util;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* OpenApi签名工具
*/
public class OpenApiSignUtils {
/**
* @Description 创建签名
* @return
* @author wxz
* @date 2021.03.22 16:47
*/
public static String createSign(Map<String, String> contentMap, String signKey) {
String str2beSigned = mapToSignStr(contentMap);
str2beSigned = str2beSigned.concat("&signKey=").concat(signKey);
return Md5Util.md5(str2beSigned);
}
/**
* @Description 验签
* @return
* @author wxz
* @date 2021.03.22 16:51
*/
public static boolean checkSign(Map<String, String> contentMap, String signKey) {
String newSign = createSign(contentMap, signKey);
return newSign.equals(contentMap.get("sign"));
}
/**
* @Description map转化为签名明文
* @return
* @author wxz
* @date 2021.03.22 16:47
*/
public static String mapToSignStr(Map<String, String> map) {
Set<String> keySet = map.keySet();
String[] keyArray = (String[])keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
for(int i = 0; i < keyArray.length; ++i) {
String key = keyArray[i];
String val = (String)map.get(key);
if (val != null && val.trim().length() > 0 && !"sign".equals(key)) {
if (!sb.toString().isEmpty()) {
sb.append("&");
}
sb.append(key).append("=").append((String)map.get(key));
}
}
return sb.toString();
}
public static void main(String[] args) {
HashMap<String, String> content = new HashMap<>();
content.put("appId", "7d98b8af2d05752b4225709c4cfd4bd0");
String secret = "3209ee9f41704482be1a1fb5873a25376f2899191ca846119d44168316bc3e44";
String sign = createSign(content, secret);
System.out.println(sign);
}
}

5
epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/exception/EpmetErrorCode.java

@ -143,7 +143,10 @@ public enum EpmetErrorCode {
TOPIC_SHIFTED_TO_ISSUE_UNDER_AUDITING(9004,"当前话题正在转议题审核"),
TOPIC_ALREADY_SHIFTED_TO_ISSUE(9005,"该话题已被转为议题,请勿重复操作"),
TOPIC_IS_HIDDEN(9006,"该话题已被屏蔽,请先解除屏蔽"),
TOPIC_IS_CLOSED(9008,"该话题已关闭,无法转为议题");
TOPIC_IS_CLOSED(9008,"该话题已关闭,无法转为议题"),
// open api异常
OPEN_API_SIGN_ERROR(9100, "签名错误");
private int code;
private String msg;

10
epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/redis/RedisKeys.java

@ -370,4 +370,14 @@ public class RedisKeys {
public static String getCustomerApiServiceKey(String customerId) {
return rootPrefix.concat("customer:thirdplat:apiservice:").concat(customerId);
}
/**
* @Description 获取openApi的accessToken的key
* @return
* @author wxz
* @date 2021.03.23 10:25
*/
public static String getOpenApiAccessTokenKey(String appId) {
return rootPrefix.concat("openapi:accesstoken:").concat(appId);
}
}

40
epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/utils/ConvertUtils.java

@ -12,11 +12,14 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
/**
* 转换工具类
@ -87,4 +90,33 @@ public class ConvertUtils {
}
return t;
}
/**
* @Description entity转map
* @return
* @author wxz
* @date 2021.03.22 16:38
*/
public static Map<String, String> entityToMap(Object bean) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
Class<?> type = bean.getClass();
Map<String, String> returnMap = new HashMap(16);
BeanInfo beanInfo = Introspector.getBeanInfo(type);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for(int i = 0; i < propertyDescriptors.length; ++i) {
PropertyDescriptor descriptor = propertyDescriptors[i];
String propertyName = descriptor.getName();
if (!"class".equals(propertyName)) {
Method readMethod = descriptor.getReadMethod();
Object result = readMethod.invoke(bean);
if (result != null) {
returnMap.put(propertyName, String.valueOf(result));
} else {
returnMap.put(propertyName, "");
}
}
}
return returnMap;
}
}

3
epmet-commons/pom.xml

@ -25,6 +25,7 @@
<module>epmet-commons-extapp-auth</module>
<module>epmet-commons-thirdplat</module>
<module>epmet-commons-rocketmq</module>
</modules>
<module>epmet-commons-security</module>
</modules>
</project>

19
epmet-module/epmet-ext/epmet-ext-client/src/main/java/com/epmet/dto/form/AccessTokenFormDTO.java

@ -0,0 +1,19 @@
package com.epmet.dto.form;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class AccessTokenFormDTO {
public interface GetAccessTokenGroup {}
// 签名字符串密文
@NotBlank(message = "签名字段不能为空", groups = { GetAccessTokenGroup.class })
private String sign;
// 应用id
@NotBlank(message = "AppId字段不能为空", groups = { GetAccessTokenGroup.class })
private String appId;
}

10
epmet-module/epmet-ext/epmet-ext-server/pom.xml

@ -21,6 +21,16 @@
</properties>
<dependencies>
<dependency>
<groupId>com.epmet</groupId>
<artifactId>common-service-client</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.epmet</groupId>
<artifactId>epmet-commons-security</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.epmet</groupId>
<artifactId>epmet-ext-client</artifactId>

15
epmet-module/epmet-ext/epmet-ext-server/src/main/java/com/epmet/config/OpenApiConfig.java

@ -0,0 +1,15 @@
package com.epmet.config;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Component
@Data
public class OpenApiConfig {
@Value("${openApi.accessToken.expire}")
private int accessTokenExpire;
}

88
epmet-module/epmet-ext/epmet-ext-server/src/main/java/com/epmet/controller/OpenApiAccessTokenController.java

@ -0,0 +1,88 @@
package com.epmet.controller;
import com.epmet.commons.security.sign.openapi.OpenApiSignUtils;
import com.epmet.commons.tools.exception.EpmetErrorCode;
import com.epmet.commons.tools.exception.ExceptionUtils;
import com.epmet.commons.tools.exception.RenException;
import com.epmet.commons.tools.redis.RedisKeys;
import com.epmet.commons.tools.redis.RedisUtils;
import com.epmet.commons.tools.utils.ConvertUtils;
import com.epmet.commons.tools.utils.Result;
import com.epmet.commons.tools.validator.ValidatorUtils;
import com.epmet.dto.form.AccessTokenFormDTO;
import com.epmet.feign.EpmetCommonServiceOpenFeignClient;
import com.epmet.service.OpenApiAccessTokenService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
@RestController
@RequestMapping("open-api")
public class OpenApiAccessTokenController {
@Autowired
private OpenApiAccessTokenService openApiAccessTokenService;
@Autowired
private EpmetCommonServiceOpenFeignClient commonServiceOpenFeignClient;
@Autowired
private RedisUtils redisUtils;
private Logger logger = LoggerFactory.getLogger(OpenApiAccessTokenController.class);
/**
* @Description 获取AccessToken
* @return
* @author wxz
* @date 2021.03.23 09:52
*/
@PostMapping("get-access-token")
public Result<String> getAccessToken(@RequestBody AccessTokenFormDTO input) {
// 1.校验参数
ValidatorUtils.validateEntity(input);
String appId = input.getAppId();
// 2.取secret
String secret = (String)redisUtils.get(RedisKeys.getExternalAppSecretKey(appId));
if (StringUtils.isBlank(secret)) {
Result<String> result = commonServiceOpenFeignClient.getSecret(appId);
if (!result.success()) {
throw new RenException("调用common service查询secret失败");
}
secret = result.getData();
if (StringUtils.isBlank(secret)) {
throw new RenException(String.format("根据appId%s没有找到对应的secret", appId));
}
redisUtils.set(RedisKeys.getExternalAppSecretKey(appId), secret);
}
// 3.验签
try {
if (!OpenApiSignUtils.checkSign(ConvertUtils.entityToMap(input), secret)) {
throw new RenException(EpmetErrorCode.OPEN_API_SIGN_ERROR.getCode(), EpmetErrorCode.OPEN_API_SIGN_ERROR.getMsg());
}
} catch (RenException e) {
// 如果是自己抛出的异常则继续抛出
throw e;
} catch (Exception e) {
// 是其他意外发生的异常
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
logger.error("验签发生未知异常:{}", errorStackTrace);
throw new RenException("验签发生未知异常,请查看ext服务详细日志");
}
//4.生成token
String accessToken = openApiAccessTokenService.getAccessToken(appId, secret);
return new Result<String>().ok(accessToken);
}
}

15
epmet-module/epmet-ext/epmet-ext-server/src/main/java/com/epmet/service/OpenApiAccessTokenService.java

@ -0,0 +1,15 @@
package com.epmet.service;
/**
* access token的service
*/
public interface OpenApiAccessTokenService {
/**
* @Description 获取AccessToken
* @return
* @author wxz
* @date 2021.03.22 22:57
*/
String getAccessToken(String appId, String secret);
}

44
epmet-module/epmet-ext/epmet-ext-server/src/main/java/com/epmet/service/impl/OpenApiAccessTokenServiceImpl.java

@ -0,0 +1,44 @@
package com.epmet.service.impl;
import com.epmet.commons.security.jwt.JwtTokenUtils;
import com.epmet.commons.tools.exception.EpmetErrorCode;
import com.epmet.commons.tools.exception.RenException;
import com.epmet.commons.tools.redis.RedisKeys;
import com.epmet.commons.tools.redis.RedisUtils;
import com.epmet.commons.tools.utils.Result;
import com.epmet.commons.tools.utils.SpringContextUtils;
import com.epmet.config.OpenApiConfig;
import com.epmet.feign.EpmetCommonServiceOpenFeignClient;
import com.epmet.service.OpenApiAccessTokenService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.HashMap;
@Service
public class OpenApiAccessTokenServiceImpl implements OpenApiAccessTokenService {
@Autowired
private JwtTokenUtils jwtTokenUtils;
@Autowired
private OpenApiConfig openApiConfig;
@Autowired
private RedisUtils redisUtils;
@Override
public String getAccessToken(String appId, String secret) {
HashMap<String, Object> claim = new HashMap<>();
claim.put("appId", appId);
String token = jwtTokenUtils.createToken(claim, openApiConfig.getAccessTokenExpire(), secret);
// 缓存token
redisUtils.set(RedisKeys.getOpenApiAccessTokenKey(appId), token, openApiConfig.getAccessTokenExpire());
return token;
}
}

5
epmet-module/epmet-ext/epmet-ext-server/src/main/resources/bootstrap.yml

@ -110,3 +110,8 @@ shutdown:
graceful:
enable: true #是否开启优雅停机
waitTimeSecs: 30 # 优雅停机等待时间,超过30秒,发出告警
# 对外开放接口配置
openApi:
accessToken:
expire: 7200000

Loading…
Cancel
Save