【C端公共业务】微信小程序登录并返回jwt token

326 阅读2分钟

通过controller层调用service层的login方法,service层代码详解如下:

1、前端获取code通过http get请求传给后端

2、后端根据微信的秘钥解析code获取openid等信息

3、解析成功返回jwt的token给前端,微信小程序前端能够通过jwt token调用后台的业务接口

Service层代码如下:

public BaseResponse login(String code) {    if (StringUtils.isBlank(code)) {        return BaseResponse.error("code is required");    }    JSONObject resJson = weChatManager.getSessionKeyOrOpenId(code);    long now = System.currentTimeMillis();    long expireAt = now + BaseConstants.EXPIRE * 1000;    resJson.put(StringConstants.EXPIRE_AT, expireAt);    resJson.put("accountType","wechat");    log.debug("resJson code:{}", resJson);    Integer errcode = resJson.getInteger("errcode");    String openid = resJson.getString("openid");    String sessionKey = resJson.getString("session_key");    try {        if (Objects.isNull(errcode)) {            if (StringUtils.isBlank(openid)) {                return BaseResponse.error("openid is blank from wechat");            }            Map<String, String> map = Maps.newHashMap();            map.put("openid", openid);            map.put("accountType","wechat");            String token = JWTUtil.generateToken(resJson, BaseConstants.PRIVATE_KEY, BaseConstants.SIGNER_KEY);            map.put("token", token);            map.put("sessionKey", sessionKey);            return BaseResponse.success(map);        }        switch (errcode) {            case 0:                Map<String, String> map = Maps.newHashMap();                map.put("openid", openid);                String token = JWTUtil.generateToken(resJson, BaseConstants.PRIVATE_KEY, BaseConstants.SIGNER_KEY);                map.put("token", token);                map.put("sessionKey", sessionKey);                return BaseResponse.success(map);             default: {                return BaseResponse.error("登录失败");            }        }    } catch (AuthException e) {        return BaseResponse.error("登录异常");    }}

Manager层代码如下

public JSONObject getSessionKeyOrOpenId(String code) {    JSONObject jsonObject = new JSONObject();    String requestUrl = BaseConstants.WECHAT_URL;    Map<String, String> requestUrlParam = new HashMap<>();    // TODO 小程序appId    requestUrlParam.put("appid", BaseConstants.APP_ID);    // TODO 小程序secret    requestUrlParam.put("secret", BaseConstants.SECRET);    //小程序端返回的code    requestUrlParam.put("js_code", code);    //默认参数    requestUrlParam.put("grant_type", "authorization_code");    //发送post请求读取调用微信接口获取openid用户唯一标识    jsonObject = JSON.parseObject(HttpClientUtil.doPost(requestUrl, requestUrlParam));    return jsonObject;}

BaseResponse公共返回参数:

@Data@AllArgsConstructorpublic class BaseResponse<T> {    int code;    String message;    T data;    public static <T> BaseResponse<T> of(T data) {        return new BaseResponse<>(200, "OK", data);    }    public static <T> BaseResponse<T> bad(int code, String message) {        return new BaseResponse<>(code, message, null);    }    public static <T> BaseResponse<T> success(T data) {        return new BaseResponse<>(200, "OK", data);    }    public static <T> BaseResponse<T> success() {        return new BaseResponse<>(200, "OK",null);    }    public static <T> BaseResponse<T> error(int code, String message) {        return new BaseResponse<>(code, message, null);    }    public static <T> BaseResponse<T> error( String message) {        return new BaseResponse<>(999, message, null);    }    public static <T> BaseResponse<T> error( int code, String message,T data) {        return new BaseResponse<>(code, message, data);    }}

JWTUtil工具类:

public class JWTUtil {    public static JSONObject checkIn(String token, String privateKey, String signerKey) throws AuthException {        JSONObject data;        try {            JWEObject jweObject = JWEObject.parse(token);            jweObject.decrypt(new DirectDecrypter(privateKey.getBytes()));            JWSObject jwsObject = jweObject.getPayload().toJWSObject();            JWSVerifier verifier = new MACVerifier(signerKey.getBytes());            if (!jwsObject.verify(verifier)) {                log.error("Couldn't parse JWS object: invalid sign!");                throw new AuthException();            }            data = JSONObject.parseObject(jwsObject.getPayload().toString());            if (log.isDebugEnabled()) {                log.debug("check token value:{}", data);            }            return data;        } catch (Exception e) {            log.error("auth check token error:", e);            throw new AuthException();        }    }    public static JSONObject check(String token, String privateKey, String signerKey) throws AuthException {        JSONObject data = checkIn(token, privateKey, signerKey);        if (data.getLongValue(StringConstants.EXPIRE_AT) <= System.currentTimeMillis()) {            log.info("token expired:{}", token);            throw new AuthException();        }        return data;    }    public static String generateToken(JSONObject value, String privateKey, String signerKey) throws AuthException {        Payload payload = new Payload(value.toJSONString());        JWSHeader headerJWS = new JWSHeader(JWSAlgorithm.HS256);        JWSObject jwsObject = new JWSObject(headerJWS, payload);        try {            jwsObject.sign(new MACSigner(signerKey.getBytes()));            JWEHeader header = new JWEHeader(JWEAlgorithm.DIR, EncryptionMethod.A128GCM);            JWEObject jweObject = new JWEObject(header, new Payload(jwsObject));            if (log.isDebugEnabled()) {                log.debug("generateToken info:{}", value);            }            jweObject.encrypt(new DirectEncrypter(privateKey.getBytes()));            return jweObject.serialize();        } catch (JOSEException e) {            log.error("generate token failed: {}", e);            throw new AuthException();        }    }}

AuthException异常类:

public class AuthException extends Exception {    private ExceptionStatus status;    public AuthException() {        super();        this.status = ExceptionStatus.UNKNOWN;    }    public AuthException(ExceptionStatus status) {        super();        this.status = status;    }}

BaseConstants用作常量存放

public interface BaseConstants {    @ApiModelProperty("微信小程序登录url")    String WECHAT_URL = "https://api.weixin.qq.com/sns/jscode2session";    @ApiModelProperty("微信小程序appId")    String APP_ID = "*************";    @ApiModelProperty("微信小程序密钥secret")    String SECRET = "";    @ApiModelProperty("过期时间")    Long EXPIRE = 259200L;    @ApiModelProperty("JWT登录用")    String PRIVATE_KEY = "*************";    @ApiModelProperty("JWT登录用")    String SIGNER_KEY= "*************";}