@ -2,10 +2,8 @@ package com.ynxbd.wx.wxfactory;
import com.ynxbd.common.bean.Patient ;
import com.ynxbd.common.bean.Patient ;
import com.ynxbd.common.bean.User ;
import com.ynxbd.common.bean.User ;
import com.ynxbd.common.helper.common.AesMicroHelper ;
import com.ynxbd.common.helper.common.* ;
import com.ynxbd.common.helper.common.Base64Helper ;
import com.ynxbd.common.helper.http.OkHttpHelper ;
import com.ynxbd.common.helper.common.CodeHelper ;
import com.ynxbd.common.helper.common.JsonHelper ;
import com.ynxbd.common.result.Result ;
import com.ynxbd.common.result.Result ;
import com.ynxbd.common.service.PatientService ;
import com.ynxbd.common.service.PatientService ;
import com.ynxbd.wx.config.WeChatConfig ;
import com.ynxbd.wx.config.WeChatConfig ;
@ -13,6 +11,8 @@ import com.ynxbd.wx.wxfactory.bean.SnsOath2AccessToken;
import com.ynxbd.wx.wxfactory.bean.SnsUserInfo ;
import com.ynxbd.wx.wxfactory.bean.SnsUserInfo ;
import com.ynxbd.wx.wxfactory.bean.auth.AuthData ;
import com.ynxbd.wx.wxfactory.bean.auth.AuthData ;
import lombok.extern.slf4j.Slf4j ;
import lombok.extern.slf4j.Slf4j ;
import okhttp3.FormBody ;
import okhttp3.RequestBody ;
import org.apache.commons.lang3.ObjectUtils ;
import org.apache.commons.lang3.ObjectUtils ;
import org.ehcache.Cache ;
import org.ehcache.Cache ;
@ -28,38 +28,48 @@ import java.util.Map;
@Slf4j
@Slf4j
public class WxAuthHelper {
public class WxAuthHelper {
private static final int SESSION_MAX_INACTIVE_INTERVAL = 60 * 60 ; // session最大存活时间 1H
private static final int SESSION_MAX_INACTIVE_INTERVAL = 60 * 60 ; // session最大存活时间 1H
public static String auth ( HttpServletRequest request , HttpServletResponse response , boolean isUserInfo ) {
public static String auth ( HttpServletRequest request , HttpServletResponse response , boolean isUserInfo ) {
String code = request . getParameter ( "code" ) ;
String code = request . getParameter ( "code" ) ;
String state = request . getParameter ( "state" ) ;
String state = request . getParameter ( "state" ) ; // base64
String hash = request . getParameter ( "hash " ) ;
String enuId = request . getParameter ( "enuId " ) ;
log . info ( "[授权] code={}, state={}, enuId={}" , code , state , enuId ) ;
try {
try {
if ( hash = = null ) {
state = state = = null ? "" : URLDecoder . decode ( Base64Helper . decode ( state ) , "UTF-8" ) ;
hash = "" ;
String enUnionId = null ;
} else {
String protocolState = null ;
hash = Base64Helper . decode ( hash ) ;
hash = URLDecoder . decode ( hash , "UTF-8" ) ;
if ( ! ObjectUtils . isEmpty ( enuId ) ) {
int index = enuId . indexOf ( "@protocolState=" ) ;
if ( index = = - 1 ) index = enuId . indexOf ( "%40protocolState=" ) ; // 防止数据转义失败
if ( index ! = - 1 ) {
enUnionId = enuId . substring ( 0 , index ) ;
protocolState = enuId . substring ( index ) ;
}
}
}
log . info ( "[授权-解码] enUnionId={}, protocolState={}, state={}" , enUnionId , protocolState , state ) ;
SnsOath2AccessToken snsToken = WxFactory . Base . OAuth ( ) . oauth2AccessToken ( WeChatConfig . APP_ID , WeChatConfig . APP_SECRET , code ) ;
SnsOath2AccessToken snsToken = WxFactory . Base . OAuth ( ) . oauth2AccessToken ( WeChatConfig . APP_ID , WeChatConfig . APP_SECRET , code ) ;
if ( snsToken ! = null ) {
if ( snsToken ! = null ) {
String openid = snsToken . getOpenid ( ) ;
String openid = snsToken . getOpenid ( ) ;
String unionId = snsToken . getUnionid ( ) ;
if ( unionId = = null ) {
log . info ( "[测试] enUnionId={}" , enUnionId ) ;
}
if ( openid ! = null ) {
if ( openid ! = null ) {
HttpSession session = request . getSession ( ) ;
HttpSession session = request . getSession ( ) ;
session . setMaxInactiveInterval ( SESSION_MAX_INACTIVE_INTERVAL ) ;
session . setMaxInactiveInterval ( SESSION_MAX_INACTIVE_INTERVAL ) ;
session . setAttribute ( "openid" , openid ) ;
session . setAttribute ( "openid" , openid ) ;
Cache < String , User > cache = WxCacheHelper . getUserCache ( ) ;
Cache < String , User > cache = WxCacheHelper . getUserCacheManager ( ) ;
if ( WeChatConfig . isDevUser ( openid ) | | ! cache . containsKey ( openid ) ) {
if ( WeChatConfig . isDevUser ( openid ) | | ! cache . containsKey ( openid ) ) {
String unionId = snsToken . getUnionid ( ) ;
User user = new User ( ) ;
User user = new User ( ) ;
user . setUnionId ( unionId ) ;
user . setUnionId ( unionId ) ;
user . setOpenid ( openid ) ;
user . setOpenid ( openid ) ;
user . setIsSnapShotUser ( snsToken . getIsSnapShotUser ( ) ) ;
user . setIsSnapShotUser ( snsToken . getIsSnapShotUser ( ) ) ;
user . setPatientList ( new PatientService ( ) . queryPatientList ( openid , unionId , true ) ) ;
user . setPatientList ( new PatientService ( ) . queryPatientList ( openid , unionId , true ) ) ;
if ( isUserInfo ) {
if ( isUserInfo ) {
@ -69,10 +79,7 @@ public class WxAuthHelper {
user . setAvatar ( snsUser . getHeadImgUrl ( ) ) ;
user . setAvatar ( snsUser . getHeadImgUrl ( ) ) ;
user . setNickName ( snsUser . getNickname_emoji ( ) ) ;
user . setNickName ( snsUser . getNickname_emoji ( ) ) ;
user . setProvince ( snsUser . getProvince ( ) ) ;
user . setProvince ( snsUser . getProvince ( ) ) ;
Integer sex = snsUser . getSex ( ) ;
user . setGenderByInt ( snsUser . getSex ( ) ) ;
if ( sex ! = null ) {
user . setGender ( sex = = 1 ? "男" : "女" ) ;
}
user . setCity ( snsUser . getCity ( ) ) ;
user . setCity ( snsUser . getCity ( ) ) ;
user . setLanguage ( snsUser . getLanguage ( ) ) ;
user . setLanguage ( snsUser . getLanguage ( ) ) ;
}
}
@ -86,10 +93,7 @@ public class WxAuthHelper {
if ( snsUser ! = null ) {
if ( snsUser ! = null ) {
user . setAvatar ( snsUser . getHeadImgUrl ( ) ) ;
user . setAvatar ( snsUser . getHeadImgUrl ( ) ) ;
user . setNickName ( snsUser . getNickname_emoji ( ) ) ;
user . setNickName ( snsUser . getNickname_emoji ( ) ) ;
Integer sex = snsUser . getSex ( ) ;
user . setGenderByInt ( snsUser . getSex ( ) ) ;
if ( sex ! = null ) {
user . setGender ( sex = = 1 ? "男" : "女" ) ;
}
}
}
}
}
}
}
@ -97,24 +101,18 @@ public class WxAuthHelper {
}
}
}
}
if ( hash = = null ) hash = "" ;
if ( state = = null ) state = "" ;
String protocol = "" ; //
int index = state . indexOf ( "@protocol=" ) ;
if ( WeChatConfig . HAS_HTTPS_BY_BASE_URL ) { // 强制为https
if ( index = = - 1 ) index = state . indexOf ( "%40protocol=" ) ; // 防止数据转义失败
String httpsURL = URLHelper . URLToHttps ( state ) ;
if ( index ! = - 1 ) {
state = httpsURL = = null ? "" : httpsURL ;
protocol = state . substring ( index ) ;
state = state . substring ( 0 , index ) ;
}
}
String domain = WeChatConfig . getBaseDomain ( WeChatConfig . HAS_HTTPS_BY_BASE_URL | | "@protocol=1" . equals ( protocol ) ) ; // 配置中baseURL有"https"时优先级最高 ["@protocol=1"为https;"@protocol=0"为默认的http;]
if ( state . contains ( ".html" ) ) { // 网页授权配置
if ( state . contains ( ".html" ) ) {
return state ;
return domain + state + hash ;
} else {
} else {
String baseUrl = WeChatConfig . getBaseUrl ( ) ;
String baseUrl = WeChatConfig . getBaseURL ( ) ;
if ( baseUrl ! = null & & state . contains ( baseUrl ) ) {
if ( baseUrl ! = null & & state . contains ( baseUrl ) ) {
return domain + state + hash ;
return state ;
}
}
}
}
} catch ( Exception e ) {
} catch ( Exception e ) {
@ -124,22 +122,50 @@ public class WxAuthHelper {
}
}
public static Result isAuth ( HttpServletRequest request ) throws Exception {
public static Result isAuth ( HttpServletRequest request , boolean isPayOAuth ) throws Exception {
HttpSession session = request . getSession ( ) ;
String token = request . getParameter ( "token" ) ; // 前端缓存
String token = request . getParameter ( "token" ) ; // 前端缓存
String state = request . getParameter ( "state" ) ;
String isUserInfo = request . getParameter ( "isUserInfo" ) ;
String protocolState = request . getParameter ( "protocolState" ) ;
String enuId = ParamHelper . filterParamNull ( request . getParameter ( "enuId" ) , "" ) ;
String deState = URLDecoder . decode ( Base64Helper . decode ( state ) , "UTF-8" ) ;
if ( WeChatConfig . IS_ENABLE_GMC & & ! WeChatConfig . IS_GMC_SERVER & & ! isPayOAuth ) { // 开启医共体开关 & 不是医共体主服务器 & 不是支付授权
try { // 请求转发
String serverDomain = WeChatConfig . getDomain ( false , false ) ;
if ( deState ! = null & & serverDomain ! = null & & ! deState . contains ( serverDomain ) ) {
return Result . error ( "授权域名不匹配" ) ;
}
RequestBody requestBody = new FormBody . Builder ( )
. add ( "token" , token )
. add ( "state" , state )
. add ( "isUserInfo" , isUserInfo )
. add ( "enuId" , enuId )
. add ( "protocolState" , protocolState )
. build ( ) ;
log . info ( "[认证请求转发] URL:[{}]" , WeChatConfig . getGMCAuthDomain ( isHttpsWithProxy ( request ) , true ) ) ;
String data = OkHttpHelper . post ( WeChatConfig . getGMCAuthDomain ( isHttpsWithProxy ( request ) , true ) + "wx_auth/is_auth" , requestBody ) ;
return Result . dataToResult ( data , true ) ;
} catch ( Exception e ) {
return Result . error ( e ) ;
}
}
boolean isFindUserInfo = ( "true" . equals ( isUserInfo ) ) ;
AuthData authData = new AuthData ( ) ;
AuthData authData = new AuthData ( ) ;
String cacheOpenid = authData . decodeToken ( token ) ;
String cacheOpenid = authData . decodeToken ( token , WeChatConfig . APP_ID ) ;
if ( cacheOpenid ! = null ) {
if ( cacheOpenid ! = null ) {
log . info ( "[微信token认证] token={}, openid={}" , token , cacheOpenid ) ;
log . info ( "[微信token认证] token={}, openid={}" , token , cacheOpenid ) ;
User user = WxCacheHelper . getCacheUser ( cacheOpenid ) ;
User user = WxCacheHelper . getCacheUser ( cacheOpenid ) ;
List < Patient > patients ;
List < Patient > patients ;
if ( user = = null ) {
if ( user = = null ) {
patients = new PatientService ( ) . queryPatientList ( cacheOpenid , null , true ) ;
patients = new PatientService ( ) . queryPatientList ( cacheOpenid , null , true ) ;
Cache < String , User > cache = WxCacheHelper . getUserCache ( ) ;
Cache < String , User > cache = WxCacheHelper . getUserCacheManager ( ) ;
User addCache = new User ( ) ;
User addCache = new User ( ) ;
addCache . setUnionId ( "" ) ;
addCache . setOpenid ( cacheOpenid ) ;
addCache . setOpenid ( cacheOpenid ) ;
addCache . setUnionId ( authData . getUnionId ( ) ) ;
addCache . setAvatar ( authData . getAvatar ( ) ) ;
addCache . setAvatar ( authData . getAvatar ( ) ) ;
addCache . setNickName ( authData . getNickName ( ) ) ;
addCache . setNickName ( authData . getNickName ( ) ) ;
addCache . setPatientList ( patients ) ;
addCache . setPatientList ( patients ) ;
@ -151,88 +177,108 @@ public class WxAuthHelper {
Map < String , Object > map = new HashMap < > ( ) ;
Map < String , Object > map = new HashMap < > ( ) ;
map . put ( "openid" , cacheOpenid ) ;
map . put ( "openid" , cacheOpenid ) ;
map . put ( "token" , token ) ;
map . put ( "token" , token ) ;
map . put ( "unionId" , "" ) ;
map . put ( "enOpenId" , AesWxHelper . encode ( cacheOpenid , true ) ) ;
map . put ( "enUnionId" , AesWxHelper . encode ( authData . getUnionId ( ) , true ) ) ;
map . put ( "date" , new Date ( ) ) ;
map . put ( "date" , new Date ( ) ) ;
map . put ( "avatar" , authData . getAvatar ( ) ) ;
map . put ( "avatar" , authData . getAvatar ( ) ) ;
map . put ( "nickName" , authData . getNickName ( ) ) ;
map . put ( "nickName" , authData . getNickName ( ) ) ;
map . put ( "patients" , CodeHelper . get28UUID ( ) + Base64Helper . encode ( URLEncoder . encode ( JsonHelper . toJsonString ( patients ) , "UTF-8" ) ) ) ;
map . put ( "patients" , CodeHelper . get28UUID ( ) + Base64Helper . encode ( URLEncoder . encode ( JsonHelper . toJsonString ( patients ) , "UTF-8" ) ) ) ;
map . put ( "hash" , request . getParameter ( "hash" ) ) ;
map . put ( "enParams" , AesMicroHelper . encode ( cacheOpenid ) ) ;
map . put ( "enParams" , AesMicroHelper . encode ( cacheOpenid ) ) ;
return Result . success ( map ) ;
return Result . success ( map ) ;
}
}
HttpSession session = request . getSession ( ) ;
Object openid = session . getAttribute ( "openid" ) ;
Object openid = session . getAttribute ( "openid" ) ;
if ( openid ! = null ) {
if ( openid ! = null ) {
log . info ( "[微信认证]openid={}" , openid ) ;
log . info ( "[微信认证]openid={}" , openid ) ;
User user = WxCacheHelper . getCacheUser ( ( String ) openid ) ;
User user = WxCacheHelper . getCacheUser ( ( String ) openid ) ;
if ( user = = null ) {
if ( user = = null ) {
return Result . success ( getAuthUrl ( request ) ) ;
return Result . success ( getAuthUrl ( request , state , isFindUserInfo , enuId , protocolState ) ) ;
}
}
String isUserInfo = request . getParameter ( "isUserInfo" ) ;
if ( isFindUserInfo ) { // 更换授权模式,需更新信息
if ( "true" . equals ( isUserInfo ) ) { // 更换授权模式,需更新信息
if ( user . getNickName ( ) = = null | | user . getAvatar ( ) = = null ) {
if ( user . getNickName ( ) = = null | | user . getAvatar ( ) = = null ) {
return Result . success ( getAuthUrl ( request ) ) ;
return Result . success ( getAuthUrl ( request , state , true , enuId , protocolState ) ) ;
}
}
}
}
Map < String , Object > map = new HashMap < > ( ) ;
Map < String , Object > map = new HashMap < > ( ) ;
map . put ( "openid" , openid ) ;
map . put ( "openid" , openid ) ;
map . put ( "token" , new AuthData ( ) . createToken ( openid . toString ( ) , user . getAvatar ( ) , user . getNickName ( ) ) ) ;
map . put ( "token" , new AuthData ( ) . createToken ( WeChatConfig . APP_ID , openid . toString ( ) , user . getUnionId ( ) , user . getAvatar ( ) , user . getNickName ( ) ) ) ;
map . put ( "unionId" , user . getUnionId ( ) ) ;
map . put ( "enOpenId" , AesWxHelper . encode ( openid . toString ( ) , true ) ) ;
map . put ( "enUnionId" , AesWxHelper . encode ( user . getUnionId ( ) , true ) ) ;
map . put ( "date" , new Date ( ) ) ;
map . put ( "date" , new Date ( ) ) ;
map . put ( "avatar" , user . getAvatar ( ) ) ;
map . put ( "avatar" , user . getAvatar ( ) ) ;
map . put ( "nickName" , user . getNickName ( ) ) ;
map . put ( "nickName" , user . getNickName ( ) ) ;
map . put ( "patients" , CodeHelper . get28UUID ( ) + Base64Helper . encode ( URLEncoder . encode ( JsonHelper . toJsonString ( user . getPatientList ( ) ) , "UTF-8" ) ) ) ;
map . put ( "patients" , CodeHelper . get28UUID ( ) + Base64Helper . encode ( URLEncoder . encode ( JsonHelper . toJsonString ( user . getPatientList ( ) ) , "UTF-8" ) ) ) ;
map . put ( "hash" , request . getParameter ( "hash" ) ) ;
map . put ( "enParams" , AesMicroHelper . encode ( openid . toString ( ) ) ) ;
map . put ( "enParams" , AesMicroHelper . encode ( openid . toString ( ) ) ) ;
return Result . success ( map ) ;
return Result . success ( map ) ;
}
}
return Result . success ( getAuthUrl ( request ) ) ;
return Result . success ( getAuthUrl ( request , state , isFindUserInfo , enuId , protocolState ) ) ;
}
}
private static final String OAUTH_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WeChatConfig . APP_ID + "&redirect_uri=" ;
private static final String OAUTH_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WeChatConfig . APP_ID + "&redirect_uri=" ;
private static String getAuthUrl ( HttpServletRequest request , String state , boolean isFindUserInfo , String enuId , String protocolState ) {
private static String getAuthUrl ( HttpServletRequest request ) {
// StringBuffer url = request.getRequestURL();
// StringBuffer url = request.getRequestURL();
// String baseUrl = url.delete(url.length() - request.getRequestURI().length(), url.length()).append(request.getServletContext().getContextPath()).append("/").toString();
// String baseUrl = url.delete(url.length() - request.getRequestURI().length(), url.length()).append(request.getServletContext().getContextPath()).append("/").toString();
String state = request . getParameter ( "state" ) ;
if ( state = = null ) {
String hash = request . getParameter ( "hash" ) ;
return null ;
String isUserInfo = request . getParameter ( "isUserInfo" ) ;
String protocolState = request . getParameter ( "protocolState" ) ; // 1:https;0:http
if ( ObjectUtils . isEmpty ( protocolState ) ) {
protocolState = "0" ;
}
}
if ( hash = = null ) {
String api = isFindUserInfo ? "u_auth" : "b_auth" ;
hash = "" ;
String scope = isFindUserInfo ? "snsapi_userinfo" : "snsapi_base" ;
}
state = OAUTH_URL + WeChatConfig . getBaseURL ( WeChatConfig . HAS_HTTPS_BY_BASE_URL | | isHttpsWithProxy ( request ) ) +
"wx_auth/" + api +
"?state=" + state +
"&response_type=code" +
"&scope=" + scope + "&forcePopup=true" +
"&enuId=" + ( enuId = = null ? "" : enuId ) +
( protocolState = = null ? "" : ( "%40protocolState=" + protocolState ) ) +
"#wechat_redirect" ;
return Base64Helper . encode ( state ) ;
}
if ( state ! = null ) {
String decode = Base64Helper . decode ( state ) ;
if ( ! decode . contains ( ".html" ) & & ! decode . contains ( ".jsp" ) ) {
decode = "my-info.html" ;
}
String api = ( "true" . equals ( isUserInfo ) ? "u_auth" : "b_auth" ) ;
// 是否为https请求
String scope = ( "true" . equals ( isUserInfo ) ? "snsapi_userinfo" : "snsapi_base" ) ;
public static boolean isHttpsWithProxy ( HttpServletRequest request ) {
// 优先检查代理头(适用于反向代理场景)
// 配置中baseURL有"https"时优先级最高
String forwardedProto = request . getHeader ( "X-Forwarded-Proto" ) ;
state = OAUTH_URL + WeChatConfig . getBaseUrlByState ( ( WeChatConfig . HAS_HTTPS_BY_BASE_URL | | "1" . equals ( protocolState ) ) ) +
if ( forwardedProto ! = null ) {
"wx_auth/" + api +
return "https" . equalsIgnoreCase ( forwardedProto ) ;
"?hash=" + hash +
"&response_type=code" +
"&scope=" + scope + "&forcePopup=true" +
"&state=" + decode +
"%40protocol=" + protocolState +
"#wechat_redirect" ;
state = Base64Helper . encode ( state ) ;
}
}
return state ;
// 未经过代理,直接检查原生请求
return request . isSecure ( ) ;
}
}
// // 医共体开启 & 不是支付授权
// private static boolean isAuthGMC(boolean isPayOAuth) {
// return WeChatConfig.IS_ENABLE_GMC && !isPayOAuth;
// }
// private static String getOAuthURL(HttpServletRequest request, boolean isPayOAuth) {
// boolean isHttps = WeChatConfig.HAS_HTTPS_BY_BASE_URL || isHttpsWithProxy(request);
// return isAuthGMC(isPayOAuth)
// ? "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WeChatConfig.GMC_AUTH_APP_ID + "&redirect_uri=" + WeChatConfig.getGMCAuthDomain(isHttps, true)
// : "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WeChatConfig.APP_ID + "&redirect_uri=" + WeChatConfig.getBaseURL(isHttps);
// }
// private static SnsOath2AccessToken getOath2AccessToken(String code, boolean isPayOAuth) {
// if (isAuthGMC(isPayOAuth)) {
// return WxFactory.Base.OAuth().oauth2AccessToken(WeChatConfig.GMC_AUTH_APP_ID, WeChatConfig.GMC_AUTH_APP_SECRET, code);
// }
// return WxFactory.Base.OAuth().oauth2AccessToken(WeChatConfig.APP_ID, WeChatConfig.APP_SECRET, code);
// }
// // 获取重定向链接
// private static String getAuthDomain(HttpServletRequest request, boolean isPayOAuth) {
// if (isAuthGMC(isPayOAuth)) {
// return WeChatConfig.getGMCAuthDomain(true, false); // 强制为https
// }
// return WeChatConfig.getDomain(WeChatConfig.HAS_HTTPS_BY_BASE_URL || isHttpsWithProxy(request)); // 配置中baseURL有"https"时优先级最高 ["@protocol=1"为https;"@protocol=0"为默认的http;]
// }
}
}