日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

spring security 实现微信登录

發布時間:2023/12/14 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring security 实现微信登录 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

介紹

上一章講解了如何用QQ實現登錄,這一回講解的是用微信實現登錄。

實現功能

實現微信登錄。

開發步驟

引入jar包

jar包的引入和QQ引入的jar包一致。

微信實體信息
/*** @author lvhaibao* @description* @date 2019/1/4 0004 9:46*/ @Data public class WeixinUserInfo {/*** 普通用戶的標識,對當前開發者帳號唯一*/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;
獲取微信用戶的api接口和實現
/*** @author lvhaibao* @description* @date 2019/1/4 0004 9:49*/ public interface Weixin {WeixinUserInfo getUserInfo(String openId); }/*** @author lvhaibao* @description* @date 2019/1/4 0004 9:50*/ public class WeixinImpl extends AbstractOAuth2ApiBinding implements Weixin {/****/private ObjectMapper objectMapper = new ObjectMapper();/*** 獲取用戶信息的url*/private static final String URL_GET_USER_INFO = "https://api.weixin.qq.com/sns/userinfo?openid=";/*** @param accessToken*/public WeixinImpl(String accessToken) {super(accessToken, TokenStrategy.ACCESS_TOKEN_PARAMETER);}/*** 默認注冊的StringHttpMessageConverter字符集為ISO-8859-1,而微信返回的是UTF-8的,所以覆蓋了原來的方法。*/@Overrideprotected List<HttpMessageConverter<?>> getMessageConverters() {List<HttpMessageConverter<?>> messageConverters = super.getMessageConverters();messageConverters.remove(0);messageConverters.add(new StringHttpMessageConverter(Charset.forName("UTF-8")));return messageConverters;}/*** 獲取微信用戶信息。*/@Overridepublic WeixinUserInfo getUserInfo(String openId) {String url = URL_GET_USER_INFO + openId;String response = getRestTemplate().getForObject(url, String.class);if(StringUtils.contains(response, "errcode")) {return null;}WeixinUserInfo profile = null;try {profile = objectMapper.readValue(response, WeixinUserInfo.class);} catch (Exception e) {e.printStackTrace();}return profile;} }
重寫AccessGrant

因為微信和QQ不同,在獲取token的同時,微信也返回了openId。因此要重寫AccessGrant。

/*** 微信的access_token信息。與標準OAuth2協議不同,微信在獲取access_token時會同時返回openId,并沒有單獨的通過accessToke換取openId的服務* 所以在這里繼承了標準AccessGrant,添加了openId字段,作為對微信access_token信息的封裝。** @author lvhaibao* @description* @date 2019/1/4 0004 9:53*/ @Data public class WeixinAccessGrant extends AccessGrant {private static final long serialVersionUID = -7243374526633186782L;private String openId;public WeixinAccessGrant() {super("");}public WeixinAccessGrant(String accessToken, String scope, String refreshToken, Long expiresIn) {super(accessToken, scope, refreshToken, expiresIn);} }
重寫OAuth2Template
/*** @author lvhaibao* @description 重寫OAuth2Template* @date 2019/1/4 0004 10:00*/ @Slf4j 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";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;}/*** 獲取access_token** @param authorizationCode* @param redirectUri* @param parameters* @return*/@Overridepublic 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);}@Overridepublic 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) {log.info("獲取access_token, 請求URL: " + accessTokenRequestUrl.toString());//發送獲取tokenString response = getRestTemplate().getForObject(accessTokenRequestUrl.toString(), String.class);log.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);}//獲取token的時候,會返回openid,保存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;}/*** 構建獲取授權碼的請求。也就是引導用戶跳轉到微信的地址。*/@Overridepublic String buildAuthenticateUrl(OAuth2Parameters parameters) {String url = super.buildAuthenticateUrl(parameters);url = url + "&appid=" + clientId + "&scope=snsapi_login";return url;}@Overridepublic String buildAuthorizeUrl(OAuth2Parameters parameters) {return buildAuthenticateUrl(parameters);}/*** 微信返回的contentType是html/text,添加相應的HttpMessageConverter來處理。*/@Overrideprotected RestTemplate createRestTemplate() {RestTemplate restTemplate = super.createRestTemplate();restTemplate.getMessageConverters().add(new StringHttpMessageConverter(Charset.forName("UTF-8")));return restTemplate;} }
編寫自己的WeixinServiceProvider
/*** 微信的OAuth2流程處理器的提供器,供spring social的connect體系調用** @author lvhaibao* @description* @date 2019/1/4 0004 10:02*/ public class WeixinServiceProvider extends AbstractOAuth2ServiceProvider<Weixin> {/*** 微信獲取授權碼的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));}@Overridepublic Weixin getApi(String accessToken) {return new WeixinImpl(accessToken);} }
編寫自己的WeixinAdapter
/*** 微信 api適配器,將微信 api的數據模型轉為spring social的標準模型。** @author lvhaibao* @description* @date 2019/1/4 0004 9:56*/ public class WeixinAdapter implements ApiAdapter<Weixin> {private String openId;public WeixinAdapter() {}public WeixinAdapter(String openId){this.openId = openId;}/*** @param api* @return*/@Overridepublic boolean test(Weixin api) {return true;}/*** @param api* @param values*/@Overridepublic void setConnectionValues(Weixin api, ConnectionValues values) {WeixinUserInfo profile = api.getUserInfo(openId);values.setProviderUserId(profile.getOpenid());values.setDisplayName(profile.getNickname());values.setImageUrl(profile.getHeadimgurl());}/*** @param api* @return*/@Overridepublic UserProfile fetchUserProfile(Weixin api) {return null;}/*** @param api* @param message*/@Overridepublic void updateStatus(Weixin api, String message) {//do nothing} }
微信連接工廠ConnectionFactory
/*** @author lvhaibao* @description 創建連接工廠* @date 2019/1/4 0004 9:59*/ public class WeixinConnectionFactory extends OAuth2ConnectionFactory<Weixin> {/*** @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來獲取*/@Overrideprotected String extractProviderUserId(AccessGrant accessGrant) {if (accessGrant instanceof WeixinAccessGrant) {return ((WeixinAccessGrant) accessGrant).getOpenId();}return null;}@Overridepublic Connection<Weixin> createConnection(AccessGrant accessGrant) {return new OAuth2Connection<Weixin>(getProviderId(), extractProviderUserId(accessGrant), accessGrant.getAccessToken(),accessGrant.getRefreshToken(), accessGrant.getExpireTime(), getOAuth2ServiceProvider(), getApiAdapter(extractProviderUserId(accessGrant)));}@Overridepublic Connection<Weixin> createConnection(ConnectionData data) {return new OAuth2Connection<Weixin>(data, getOAuth2ServiceProvider(), getApiAdapter(data.getProviderUserId()));}private ApiAdapter<Weixin> getApiAdapter(String providerUserId) {return new WeixinAdapter(providerUserId);}private OAuth2ServiceProvider<Weixin> getOAuth2ServiceProvider() {return (OAuth2ServiceProvider<Weixin>) getServiceProvider();} }
自定義微信的服務提供商Id
/*** @author lvhaibao* @description 自定義微信的服務提供商ID* @date 2019/1/4 0004 9:47*/ @Data public class WeixinProperties extends SocialProperties {private String providerId = "weixin";}
編寫配置applicaion.yml
system: #客戶端配置social:filterProcessesUrl: /qqLoginweixin:app-id: wx8a47a66e22296c62app-secret: deb57af7ec1753a2668889e74b34b789
頁面

頁面中添加這個鏈接就好。

<a href="/qqLogin/weixin">微信登錄</a>

還有其他的配置在上一章中已經寫好。讀者可自行查閱或者查看項目源碼。

測試

和QQ登錄一樣。這里就不再進行敘述。

項目源碼

https://gitee.com/lvhaibao/spring-lhbauth/tree/42327d841a8d606bf5b5167c7ecabe72040ec735/

總結

以上是生活随笔為你收集整理的spring security 实现微信登录的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。