package com.markor.common.mvc.token;
import com.alibaba.fastjson.JSON;
import com.markor.common.mvc.sKey.CurrentSKey;
import com.markor.common.mvc.sKey.SKeyManager;
import com.markor.common.mvc.sKey.bo.SkeyInfo;
import com.markor.common.mvc.token.bo.TokenUserInfo;
import com.markor.common.mvc.token.jwt.JWTConstance;
import com.markor.common.mvc.token.jwt.JWTUtil;
import mk.marketing.wechat.program.WechatProgramUser;
import mk.marketing.wechat.program.corp.CorpAppToken;
import mk.marketing.wechat.program.corp.TokenManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
* @author sunnannan
* @Title: CurrentUserMethodArgumentResolver
* @ProjectName mk-marketing-service
* @Description: 自定义controller 参数解析器 配合注解使用 当controller中存在这个类型的参数和注解,会将request中保存的token'信息写入
* @date 2018/10/1815:29
*/
@Service
public class CurrentUserMethodArgumentResolver implements HandlerMethodArgumentResolver {
private static final String HEADER_SOURCE_GATEWAY = "zuul-source-gateway";
private static final String HEADER_APP_CODE = "zuul-wechat-corp-app-code";
private static final String HEADER_ACCOUNT_NAME = "zuul-wechat-corp-account-name";
private static final String HEADER_WX_USER_ID = "zuul-wechat-wx-user-id";
@Autowired
private SKeyManager sKeyManager;
@Autowired
private TokenManager tokenManager;
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
if (methodParameter.hasParameterAnnotation(CurrentUser.class) &&
(methodParameter.getParameterType().isAssignableFrom(TokenUserInfo.class)
|| methodParameter.getParameterType().isAssignableFrom(WechatProgramUser.class)
|| methodParameter.getParameterType().isAssignableFrom(CorpAppToken.class))) {
return true;
}
if (methodParameter.getParameterType().isAssignableFrom(SkeyInfo.class) && methodParameter.hasParameterAnnotation(CurrentSKey.class)) {
return true;
}
return false;
}
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
if (methodParameter.hasParameterAnnotation(CurrentUser.class)) {
// 获取头信息"zuul-source-gateway",得到该请求时从哪个代理转发过来的(企业应用Gateway/C端用户Gateway/后台管理Gateway)
String sourceGateway = nativeWebRequest.getHeader(HEADER_SOURCE_GATEWAY);
if ("wechat-corp-gateway".equals(sourceGateway)) { // -------------------------------- wechat-corp-gateway 企业应用
/*
因为wechat-corp-gateway要对访问的接口做业务登录校验过滤,因此解析Token的动作在gateway中已完成,解析后的appCode和
accountName直接通过header传递进来
*/
String appCode = nativeWebRequest.getHeader(HEADER_APP_CODE);
String accountName = nativeWebRequest.getHeader(HEADER_ACCOUNT_NAME);
if (methodParameter.getParameterType().isAssignableFrom(TokenUserInfo.class)) { // 返回系统用户会话信息
String userInfoJson = tokenManager.getCurrentUserInfo(appCode, accountName);
if (userInfoJson != null) {
return JSON.parseObject(userInfoJson, TokenUserInfo.class);
}
} else if (methodParameter.getParameterType().isAssignableFrom(WechatProgramUser.class)) { // 返回微信用户信息
return tokenManager.getWechatProgramUserInfo(appCode, nativeWebRequest.getHeader(HEADER_WX_USER_ID));
} else if (methodParameter.getParameterType().isAssignableFrom(CorpAppToken.class)) { // 返回微信登录Token
return tokenManager.parseToken(nativeWebRequest.getHeader(JWTConstance.TOKEN_INFO));
}
} else if ("admin-gateway".equals(sourceGateway)) { // -------------------------------- admin-gateway 后台管理
String tokenStr = nativeWebRequest.getHeader(JWTConstance.TOKEN_INFO);
if (!StringUtils.isEmpty(tokenStr)) {
String userInfo = JWTUtil.getUserInfo(tokenStr);
if (!StringUtils.isEmpty(userInfo)) {
TokenUserInfo tokenUserInfo = JSON.parseObject(userInfo, TokenUserInfo.class);
tokenUserInfo.setToken(tokenStr);
return tokenUserInfo;
} else {
throw new Exception("参数解析器:获取token信息失败");
}
}
} else if ("public-gateway".equals(sourceGateway)) { // -------------------------------- public-gateway C端程序访问入口
String tokenStr = nativeWebRequest.getHeader(JWTConstance.TOKEN_INFO);
CorpAppToken token = tokenManager.parseToken(tokenStr);
if (methodParameter.getParameterType().isAssignableFrom(WechatProgramUser.class)) {
return tokenManager.getWechatProgramUserInfo(token.getAppCode(), token.getWxUserId());
} else if (methodParameter.getParameterType().isAssignableFrom(CorpAppToken.class)) {
return token;
}
}
return null;
}
if (methodParameter.hasParameterAnnotation(CurrentSKey.class)) {
String sKey = nativeWebRequest.getHeader("sKey");
String sKeyInfoJsonStr = sKeyManager.getSkeyInfo(sKey);
SkeyInfo skeyInfo = new SkeyInfo();
if (!StringUtils.isEmpty(sKeyInfoJsonStr)) {
skeyInfo.setUnionId(JSON.parseObject(sKeyInfoJsonStr).getString("unionid"));
skeyInfo.setSessionKey(JSON.parseObject(sKeyInfoJsonStr).getString("session_key"));
skeyInfo.setOpenId(JSON.parseObject(sKeyInfoJsonStr).getString("openid"));
skeyInfo.setSkeyUrl(sKey);
} else {
throw new Exception("参数解析器:获取Skey信息失败");
}
return skeyInfo;
}
return null;
}
}