微信登录初步开发完毕
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
- `/authentication/require`处理身份认证跳转的接口地址
|
||||
- 需要注入`userServiceImpl`获取用户详细信息的bean (必须参数)
|
||||
- 需要注入数据源`masterDataSource`用于记住我功能的bean,记住我功能需要在登录的时候传入(必须参数)
|
||||
### 第三方方登录的配置
|
||||
- 使用这个模块的时候需要借助providerSignInUtils.doPostSignUp();方法实现一个接口将用户的注册或绑定信息插入到数据表中,这里的注
|
||||
册指的是创建本系统自己的用户体系,第三方的用户体系springSocial会自动帮助我们创建。并将url
|
||||
配置可以直接访问
|
||||
|
||||
+1
-1
@@ -130,7 +130,7 @@ public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
, "/upms/user"
|
||||
//用户注册或绑定的页面
|
||||
,securityProperties.getBrowser().getSignUpUrl()
|
||||
,"用户的注册绑定url")
|
||||
,"处理用户的注册绑定请求的url")
|
||||
.permitAll()
|
||||
//任何请求
|
||||
.anyRequest()
|
||||
|
||||
@@ -24,9 +24,13 @@
|
||||
- `ms.security.createRememberTable` 是否创建记住我表结构默认为`true`
|
||||
|
||||
### 本项目提供的第三方登录的配置
|
||||
qq 第三方登录
|
||||
- `ms.security.social.qq.appId` qq互联注册的id
|
||||
- `ms.security.social.qq.appSecret` qq互联注册的密码
|
||||
- `ms.security.social.qq.providerId` 第三方登录的标识,例如qq为`qq`登陆默认
|
||||
- `ms.security.social.qq.filterProcessUrl` 进行第三方登录处理的基础url前缀,这个前缀会和providerId进行拼接来进行明确
|
||||
- `ms.security.social.filterProcessUrl` 进行第三方登录处理的基础url前缀,这个前缀会和providerId进行拼接来进行明确
|
||||
的第三方登录,这个地址也是从第三方应用携带授权码返回的时候进行处理的地址,如果没有授权码就重定向到第三方登录
|
||||
|
||||
weChat 第三方登录
|
||||
- `ms.security.social.weChat.appId` 类比qq登录
|
||||
- `ms.security.social.weChat.appSecret` 类比qq登录
|
||||
- `ms.security.social.weChat.providerId` 类比qq登录
|
||||
|
||||
+21
@@ -1,16 +1,37 @@
|
||||
package com.micro.fast.security.core.social;
|
||||
|
||||
import com.micro.fast.security.core.social.qq.QQSocialProperties;
|
||||
import com.micro.fast.security.core.social.wechat.WeChatSocialProperties;
|
||||
import com.micro.fast.security.core.social.wechat.api.WeChat;
|
||||
|
||||
/**
|
||||
* 第三方登录配置类
|
||||
* @author lsy
|
||||
*/
|
||||
public class SocialProperties {
|
||||
/**
|
||||
* QQ登录配置
|
||||
*/
|
||||
private QQSocialProperties qq = new QQSocialProperties();
|
||||
|
||||
/**
|
||||
* 微信登录配置
|
||||
*/
|
||||
private WeChatSocialProperties weChat = new WeChatSocialProperties();
|
||||
|
||||
/**
|
||||
* 第三方登录拦截url的配置
|
||||
*/
|
||||
private String filterProcessUrl = "/auth";
|
||||
|
||||
public WeChatSocialProperties getWeChat() {
|
||||
return weChat;
|
||||
}
|
||||
|
||||
public void setWeChat(WeChatSocialProperties weChat) {
|
||||
this.weChat = weChat;
|
||||
}
|
||||
|
||||
public QQSocialProperties getQq() {
|
||||
return qq;
|
||||
}
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.micro.fast.security.core.social.wechat;
|
||||
|
||||
|
||||
import org.springframework.boot.autoconfigure.social.SocialProperties;
|
||||
|
||||
/**
|
||||
* weChat第三方登录配置类
|
||||
* @author lsy
|
||||
*/
|
||||
public class WeChatSocialProperties extends SocialProperties {
|
||||
/**
|
||||
* 第三方登录标识
|
||||
*/
|
||||
private String providerId = "weChat";
|
||||
|
||||
public String getProviderId() {
|
||||
return providerId;
|
||||
}
|
||||
|
||||
public void setProviderId(String providerId) {
|
||||
this.providerId = providerId;
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.micro.fast.security.core.social.wechat.api;
|
||||
|
||||
/**
|
||||
* weChat 获取用户信息的接口
|
||||
* @author lsy
|
||||
*/
|
||||
public interface WeChat {
|
||||
/**
|
||||
* 获取微信登录用户的信息
|
||||
* @return
|
||||
*/
|
||||
WeChatUserInfo getWeChatUserInfo(String openId);
|
||||
}
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
package com.micro.fast.security.core.social.wechat.api;
|
||||
|
||||
/**
|
||||
* 微信登录用户的第三方信息
|
||||
* @author lsy
|
||||
*/
|
||||
public class WeChatUserInfo {
|
||||
/**
|
||||
* 普通用户的标识,对当前开发者帐号唯一
|
||||
*/
|
||||
private String openid;
|
||||
/**
|
||||
* 普通用户昵称
|
||||
*/
|
||||
private String nickname;
|
||||
/**
|
||||
* 语言
|
||||
*/
|
||||
private String language;
|
||||
/**
|
||||
* 普通用户性别,1为男性,2为女性
|
||||
*/
|
||||
private String sex;
|
||||
/**
|
||||
* 普通用户个人资料填写的省份
|
||||
*/
|
||||
private String province;
|
||||
/**
|
||||
* 普通用户个人资料填写的城市
|
||||
*/
|
||||
private String city;
|
||||
/**
|
||||
* 国家,如中国为CN
|
||||
*/
|
||||
private String country;
|
||||
/**
|
||||
* 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空
|
||||
*/
|
||||
private String headimgurl;
|
||||
/**
|
||||
* 用户特权信息,json数组,如微信沃卡用户为(chinaunicom)
|
||||
*/
|
||||
private String[] privilege;
|
||||
/**
|
||||
* 用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。
|
||||
*/
|
||||
private String unionid;
|
||||
|
||||
/**
|
||||
* @return the openid
|
||||
*/
|
||||
public String getOpenid() {
|
||||
return openid;
|
||||
}
|
||||
/**
|
||||
* @param openid the openid to set
|
||||
*/
|
||||
public void setOpenid(String openid) {
|
||||
this.openid = openid;
|
||||
}
|
||||
/**
|
||||
* @return the nickname
|
||||
*/
|
||||
public String getNickname() {
|
||||
return nickname;
|
||||
}
|
||||
/**
|
||||
* @param nickname the nickname to set
|
||||
*/
|
||||
public void setNickname(String nickname) {
|
||||
this.nickname = nickname;
|
||||
}
|
||||
/**
|
||||
* @return the sex
|
||||
*/
|
||||
public String getSex() {
|
||||
return sex;
|
||||
}
|
||||
/**
|
||||
* @param sex the sex to set
|
||||
*/
|
||||
public void setSex(String sex) {
|
||||
this.sex = sex;
|
||||
}
|
||||
/**
|
||||
* @return the province
|
||||
*/
|
||||
public String getProvince() {
|
||||
return province;
|
||||
}
|
||||
/**
|
||||
* @param province the province to set
|
||||
*/
|
||||
public void setProvince(String province) {
|
||||
this.province = province;
|
||||
}
|
||||
/**
|
||||
* @return the city
|
||||
*/
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
/**
|
||||
* @param city the city to set
|
||||
*/
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
/**
|
||||
* @return the country
|
||||
*/
|
||||
public String getCountry() {
|
||||
return country;
|
||||
}
|
||||
/**
|
||||
* @param country the country to set
|
||||
*/
|
||||
public void setCountry(String country) {
|
||||
this.country = country;
|
||||
}
|
||||
/**
|
||||
* @return the headimgurl
|
||||
*/
|
||||
public String getHeadimgurl() {
|
||||
return headimgurl;
|
||||
}
|
||||
/**
|
||||
* @param headimgurl the headimgurl to set
|
||||
*/
|
||||
public void setHeadimgurl(String headimgurl) {
|
||||
this.headimgurl = headimgurl;
|
||||
}
|
||||
/**
|
||||
* @return the privilege
|
||||
*/
|
||||
public String[] getPrivilege() {
|
||||
return privilege;
|
||||
}
|
||||
/**
|
||||
* @param privilege the privilege to set
|
||||
*/
|
||||
public void setPrivilege(String[] privilege) {
|
||||
this.privilege = privilege;
|
||||
}
|
||||
/**
|
||||
* @return the unionid
|
||||
*/
|
||||
public String getUnionid() {
|
||||
return unionid;
|
||||
}
|
||||
/**
|
||||
* @param unionid the unionid to set
|
||||
*/
|
||||
public void setUnionid(String unionid) {
|
||||
this.unionid = unionid;
|
||||
}
|
||||
/**
|
||||
* @return the language
|
||||
*/
|
||||
public String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
/**
|
||||
* @param language the language to set
|
||||
*/
|
||||
public void setLanguage(String language) {
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package com.micro.fast.security.core.social.wechat.api.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.micro.fast.security.core.social.wechat.api.WeChat;
|
||||
import com.micro.fast.security.core.social.wechat.api.WeChatUserInfo;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.social.oauth2.AbstractOAuth2ApiBinding;
|
||||
import org.springframework.social.oauth2.TokenStrategy;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* weChat获取用户信息接口的实现类,微信实现的并不是标准的OAuth2协议
|
||||
* @author lsy
|
||||
*/
|
||||
public class WeChatImpl extends AbstractOAuth2ApiBinding implements WeChat {
|
||||
|
||||
/**
|
||||
* 微信接口获取用户信息的url
|
||||
*/
|
||||
private static final String URL_GET_USER_INFO = "https://api.weixin.qq.com/sns/userinfo?openid=";
|
||||
|
||||
private ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
/**
|
||||
* @param accessToken
|
||||
*/
|
||||
public WeChatImpl(String accessToken) {
|
||||
super(accessToken, TokenStrategy.ACCESS_TOKEN_PARAMETER);
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认注册的StringHttpMessageConverter字符集为ISO-8859-1,而微信返回的是UTF-8的,所以覆盖了原来的方法。
|
||||
*/
|
||||
@Override
|
||||
protected List<HttpMessageConverter<?>> getMessageConverters() {
|
||||
List<HttpMessageConverter<?>> messageConverters = super.getMessageConverters();
|
||||
messageConverters.remove(0);
|
||||
messageConverters.add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
|
||||
return messageConverters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeChatUserInfo getWeChatUserInfo(String openId) {
|
||||
String url = URL_GET_USER_INFO + openId;
|
||||
String response = getRestTemplate().getForObject(url, String.class);
|
||||
if(StringUtils.contains(response, "errcode")) {
|
||||
return null;
|
||||
}
|
||||
WeChatUserInfo profile = null;
|
||||
try {
|
||||
profile = objectMapper.readValue(response, WeChatUserInfo.class);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("获取用户信息失败");
|
||||
}
|
||||
return profile;
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
package com.micro.fast.security.core.social.wechat.api.impl;
|
||||
+1
@@ -0,0 +1 @@
|
||||
package com.micro.fast.security.core.social.wechat.api;
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package com.micro.fast.security.core.social.wechat.config;
|
||||
|
||||
import com.micro.fast.security.core.master.SecurityProperties;
|
||||
import com.micro.fast.security.core.social.wechat.WeChatSocialProperties;
|
||||
import com.micro.fast.security.core.social.wechat.connet.WeixinConnectionFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.social.SocialAutoConfigurerAdapter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.social.connect.ConnectionFactory;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 微信登录配置
|
||||
* @author lsy
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "ms.security.social.weChat", name = "app-id")
|
||||
public class WeixinAutoConfiguration extends SocialAutoConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private SecurityProperties securityProperties;
|
||||
|
||||
@Override
|
||||
protected ConnectionFactory<?> createConnectionFactory() {
|
||||
WeChatSocialProperties weChatConfig = securityProperties.getSocial().getWeChat();
|
||||
return new WeixinConnectionFactory(weChatConfig.getProviderId(), weChatConfig.getAppId(),
|
||||
weChatConfig.getAppSecret());
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
package com.micro.fast.security.core.social.wechat.config;
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package com.micro.fast.security.core.social.wechat.connet;
|
||||
|
||||
import org.springframework.social.oauth2.AccessGrant;
|
||||
|
||||
/**
|
||||
* 微信的access_token信息。与标准OAuth2协议不同,微信在获取access_token时会同时返回openId,并没有单独的通过accessToke换取openId的服务
|
||||
* 所以在这里继承了标准AccessGrant,添加了openId字段,作为对微信access_token信息的封装。
|
||||
* @author lsy
|
||||
*/
|
||||
public class WeixinAccessGrant extends AccessGrant {
|
||||
|
||||
|
||||
private String openId;
|
||||
|
||||
public WeixinAccessGrant() {
|
||||
super("");
|
||||
}
|
||||
|
||||
public WeixinAccessGrant(String accessToken, String scope, String refreshToken, Long expiresIn) {
|
||||
super(accessToken, scope, refreshToken, expiresIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the openId
|
||||
*/
|
||||
public String getOpenId() {
|
||||
return openId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param openId the openId to set
|
||||
*/
|
||||
public void setOpenId(String openId) {
|
||||
this.openId = openId;
|
||||
}
|
||||
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package com.micro.fast.security.core.social.wechat.connet;
|
||||
|
||||
import com.micro.fast.security.core.social.wechat.api.WeChat;
|
||||
import com.micro.fast.security.core.social.wechat.api.WeChatUserInfo;
|
||||
import org.springframework.social.connect.ApiAdapter;
|
||||
import org.springframework.social.connect.ConnectionValues;
|
||||
import org.springframework.social.connect.UserProfile;
|
||||
|
||||
/**
|
||||
* 微信 api适配器,将微信 api的数据模型转为spring social的标准模型。
|
||||
* @author lsy
|
||||
*/
|
||||
public class WeixinAdapter implements ApiAdapter<WeChat> {
|
||||
|
||||
private String openId;
|
||||
|
||||
public WeixinAdapter() {}
|
||||
|
||||
public WeixinAdapter(String openId){
|
||||
this.openId = openId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param api
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean test(WeChat api) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param api
|
||||
* @param values
|
||||
*/
|
||||
@Override
|
||||
public void setConnectionValues(WeChat api, ConnectionValues values) {
|
||||
WeChatUserInfo profile = api.getWeChatUserInfo(openId);
|
||||
values.setProviderUserId(profile.getOpenid());
|
||||
values.setDisplayName(profile.getNickname());
|
||||
values.setImageUrl(profile.getHeadimgurl());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param api
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public UserProfile fetchUserProfile(WeChat api) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param api
|
||||
* @param message
|
||||
*/
|
||||
@Override
|
||||
public void updateStatus(WeChat api, String message) {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package com.micro.fast.security.core.social.wechat.connet;
|
||||
|
||||
import com.micro.fast.security.core.social.wechat.api.WeChat;
|
||||
import org.springframework.social.connect.ApiAdapter;
|
||||
import org.springframework.social.connect.Connection;
|
||||
import org.springframework.social.connect.ConnectionData;
|
||||
import org.springframework.social.connect.support.OAuth2Connection;
|
||||
import org.springframework.social.connect.support.OAuth2ConnectionFactory;
|
||||
import org.springframework.social.oauth2.AccessGrant;
|
||||
import org.springframework.social.oauth2.OAuth2ServiceProvider;
|
||||
|
||||
/**
|
||||
* 微信连接工厂
|
||||
*
|
||||
*
|
||||
* @author lsy
|
||||
*/
|
||||
public class WeixinConnectionFactory extends OAuth2ConnectionFactory<WeChat> {
|
||||
|
||||
/**
|
||||
* @param appId
|
||||
* @param appSecret
|
||||
*/
|
||||
public WeixinConnectionFactory(String providerId, String appId, String appSecret) {
|
||||
super(providerId, new WeixinServiceProvider(appId, appSecret), new WeixinAdapter());
|
||||
}
|
||||
|
||||
/**
|
||||
* 由于微信的openId是和accessToken一起返回的,所以在这里直接根据accessToken设置providerUserId即可,不用像QQ那样通过QQAdapter来获取
|
||||
*/
|
||||
@Override
|
||||
protected String extractProviderUserId(AccessGrant accessGrant) {
|
||||
if(accessGrant instanceof WeixinAccessGrant) {
|
||||
return ((WeixinAccessGrant)accessGrant).getOpenId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param accessGrant
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Connection<WeChat> createConnection(AccessGrant accessGrant) {
|
||||
return new OAuth2Connection<WeChat>(getProviderId(), extractProviderUserId(accessGrant), accessGrant.getAccessToken(),
|
||||
accessGrant.getRefreshToken(), accessGrant.getExpireTime(), getOAuth2ServiceProvider(), getApiAdapter(extractProviderUserId(accessGrant)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Connection<WeChat> createConnection(ConnectionData data) {
|
||||
return new OAuth2Connection<WeChat>(data, getOAuth2ServiceProvider(), getApiAdapter(data.getProviderUserId()));
|
||||
}
|
||||
|
||||
private ApiAdapter<WeChat> getApiAdapter(String providerUserId) {
|
||||
return new WeixinAdapter(providerUserId);
|
||||
}
|
||||
|
||||
private OAuth2ServiceProvider<WeChat> getOAuth2ServiceProvider() {
|
||||
return (OAuth2ServiceProvider<WeChat>) getServiceProvider();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package com.micro.fast.security.core.social.wechat.connet;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.social.oauth2.AccessGrant;
|
||||
import org.springframework.social.oauth2.OAuth2Parameters;
|
||||
import org.springframework.social.oauth2.OAuth2Template;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* 完成微信的OAuth2认证流程的模板类。国内厂商实现的OAuth2每个都不同, spring默认提供的OAuth2Template适应不了,只能针对每个厂商自己微调。
|
||||
* @author lsy
|
||||
*/
|
||||
public class WeixinOAuth2Template extends OAuth2Template {
|
||||
|
||||
private String clientId;
|
||||
|
||||
private String clientSecret;
|
||||
|
||||
private String accessTokenUrl;
|
||||
|
||||
private static final String REFRESH_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/refresh_token";
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
public WeixinOAuth2Template(String clientId, String clientSecret, String authorizeUrl, String accessTokenUrl) {
|
||||
super(clientId, clientSecret, authorizeUrl, accessTokenUrl);
|
||||
setUseParametersForClientAuthentication(true);
|
||||
this.clientId = clientId;
|
||||
this.clientSecret = clientSecret;
|
||||
this.accessTokenUrl = accessTokenUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.springframework.social.oauth2.OAuth2Template#exchangeForAccess(java.lang.String, java.lang.String, org.springframework.util.MultiValueMap)
|
||||
*/
|
||||
@Override
|
||||
public AccessGrant exchangeForAccess(String authorizationCode, String redirectUri,
|
||||
MultiValueMap<String, String> parameters) {
|
||||
StringBuilder accessTokenRequestUrl = new StringBuilder(accessTokenUrl);
|
||||
accessTokenRequestUrl.append("?appid="+clientId);
|
||||
accessTokenRequestUrl.append("&secret="+clientSecret);
|
||||
accessTokenRequestUrl.append("&code="+authorizationCode);
|
||||
accessTokenRequestUrl.append("&grant_type=authorization_code");
|
||||
accessTokenRequestUrl.append("&redirect_uri="+redirectUri);
|
||||
return getAccessToken(accessTokenRequestUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessGrant refreshAccess(String refreshToken, MultiValueMap<String, String> additionalParameters) {
|
||||
|
||||
StringBuilder refreshTokenUrl = new StringBuilder(REFRESH_TOKEN_URL);
|
||||
|
||||
refreshTokenUrl.append("?appid="+clientId);
|
||||
refreshTokenUrl.append("&grant_type=refresh_token");
|
||||
refreshTokenUrl.append("&refresh_token="+refreshToken);
|
||||
|
||||
return getAccessToken(refreshTokenUrl);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private AccessGrant getAccessToken(StringBuilder accessTokenRequestUrl) {
|
||||
|
||||
logger.info("获取access_token, 请求URL: "+accessTokenRequestUrl.toString());
|
||||
|
||||
String response = getRestTemplate().getForObject(accessTokenRequestUrl.toString(), String.class);
|
||||
|
||||
logger.info("获取access_token, 响应内容: "+response);
|
||||
|
||||
Map<String, Object> result = null;
|
||||
try {
|
||||
result = new ObjectMapper().readValue(response, Map.class);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
//返回错误码时直接返回空
|
||||
if(StringUtils.isNotBlank(MapUtils.getString(result, "errcode"))){
|
||||
String errcode = MapUtils.getString(result, "errcode");
|
||||
String errmsg = MapUtils.getString(result, "errmsg");
|
||||
throw new RuntimeException("获取access token失败, errcode:"+errcode+", errmsg:"+errmsg);
|
||||
}
|
||||
|
||||
WeixinAccessGrant accessToken = new WeixinAccessGrant(
|
||||
MapUtils.getString(result, "access_token"),
|
||||
MapUtils.getString(result, "scope"),
|
||||
MapUtils.getString(result, "refresh_token"),
|
||||
MapUtils.getLong(result, "expires_in"));
|
||||
|
||||
accessToken.setOpenId(MapUtils.getString(result, "openid"));
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建获取授权码的请求。也就是引导用户跳转到微信的地址。
|
||||
*/
|
||||
@Override
|
||||
public String buildAuthenticateUrl(OAuth2Parameters parameters) {
|
||||
String url = super.buildAuthenticateUrl(parameters);
|
||||
url = url + "&appid="+clientId+"&scope=snsapi_login";
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildAuthorizeUrl(OAuth2Parameters parameters) {
|
||||
return buildAuthenticateUrl(parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信返回的contentType是html/text,添加相应的HttpMessageConverter来处理。
|
||||
*/
|
||||
@Override
|
||||
protected RestTemplate createRestTemplate() {
|
||||
RestTemplate restTemplate = super.createRestTemplate();
|
||||
restTemplate.getMessageConverters().add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
|
||||
return restTemplate;
|
||||
}
|
||||
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package com.micro.fast.security.core.social.wechat.connet;
|
||||
|
||||
import com.micro.fast.security.core.social.wechat.api.WeChat;
|
||||
import com.micro.fast.security.core.social.wechat.api.impl.WeChatImpl;
|
||||
import org.springframework.social.oauth2.AbstractOAuth2ServiceProvider;
|
||||
|
||||
/**
|
||||
*
|
||||
* 微信的OAuth2流程处理器的提供器,供spring social的connect体系调用
|
||||
*
|
||||
* @author zhailiang
|
||||
*
|
||||
*/
|
||||
public class WeixinServiceProvider extends AbstractOAuth2ServiceProvider<WeChat> {
|
||||
|
||||
/**
|
||||
* 微信获取授权码的url
|
||||
*/
|
||||
private static final String URL_AUTHORIZE = "https://open.weixin.qq.com/connect/qrconnect";
|
||||
/**
|
||||
* 微信获取accessToken的url
|
||||
*/
|
||||
private static final String URL_ACCESS_TOKEN = "https://api.weixin.qq.com/sns/oauth2/access_token";
|
||||
|
||||
/**
|
||||
* @param appId
|
||||
* @param appSecret
|
||||
*/
|
||||
public WeixinServiceProvider(String appId, String appSecret) {
|
||||
super(new WeixinOAuth2Template(appId, appSecret,URL_AUTHORIZE,URL_ACCESS_TOKEN));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public WeChat getApi(String accessToken) {
|
||||
return new WeChatImpl(accessToken);
|
||||
}
|
||||
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
package com.micro.fast.security.core.social.wechat.connet;
|
||||
Reference in New Issue
Block a user