基于Spring的微信第三方登录实现

来源:互联网 发布:php源码怎么安装 编辑:程序博客网 时间:2024/06/05 12:48

在前几篇文章中,我们介绍了OAuth2.0认证和授权机制讲解,并实现了基于Spring的Github第三方登录--通用化的第三方登陆实现,之后,我们基于该通用化的框架,介绍了国内的两个比较流行的第三方登录平台:基于Spring的新浪微博第三方登录实现和基于Spring的QQ第三方登录实现。以上几个第三方登录平台都严格遵守了OAuth2.0协议。但是,近来作者发现微信的第三方登录确不是那么严格的遵守通用化的OAuth2.0协议,有些细节实现不太一样(例如获取AccessToken时其他OAuth平台用的字段名为client_id,但是微信中是appid),这就导致了之前的通用化框架在微信登录时遇到了很多问题,今天我们就来介绍一下微信的第三方登录,并重构一下我们的通用化框架,使之在遇到其他不那么严格遵守OAuth协议的平台依然简单实用。

申请第三方应用

接下来我们首先来看看如何在微信开放平台中申请一个第三方应用。

首先,我们需要完善开发者资质认证,在导航栏选择【账号中心】,然后选择【开发者资质认证】,我们会看到如下页面:

alter-text

从页面信息介绍中的第二点我们可以知道,通过开发者资质认证后,我们就能够获得微信第三方登录的能力。需要注意:个人是不能申请第三方认证的,必须为以下机构或者团体才能进行认证,每次审核需要花费300元:

alter-text

开发者资质认证提交并缴费后,会在两个工作日内进行审核,如果有问题会有客服人员电话沟通。

审核完成后,进入【管理中心】-> 【网站应用】。

alter-text

点击【创建网站应用】,按照其提示填写相关内容即可:

alter-text

alter-text

提交完成后,如果你的开发者资质已经通过,就可以直接进行开发上线啦。现在,让我们看看如何添加微信第三方登录的代码。

第三方登录通用架构

现在,我们将基于Spring的Github第三方登录--通用化的第三方登陆实现中的通用化架构添加到代码中来,以此为基础添加微信登录的相关功能:

alter-text

微信第三方登录服务分析

首先,让我们我们看看微信登录开发文档,看过之后,我们发现微信登录虽然是基于OAuth2.0协议,但是API的参数确不一样。之前我们做过github、微博、QQ其获取Access Token时所需的参数为client_id以及client_secret,Scribe默认的OAuthService在处理也是同样的参数,因此我们可以通过其默认的OAuth20ServiceImpl来处理OAuth的相关操作。

但是微信中client_idclient_secret两个参数统一用的是:appidsecret。这也就意味着我们需要实现自己的WeixinOAuth20Service来对这些细节进行处理。同时,添加完成后,我们还需要添加一个WeixinOAuthDeractorService来适配通用化的第三方登陆实现中的设计。

但是WeixinOAuth20Service以及WeixinOAuthDeractorService实际上功能是一样的,只是我们需要一个CustomOAuthService来对OAuthService进行管理。如果我们通过一个接口对OAuthService进行管理的话,我们就只需要添加一个类WeixinOAuthService即可,同时这也符合依赖于接口而不是实现的最佳原则。

通过接口管理OAuthService

我们首先来添加一个接口CustomOAuthService:

public interface CustomOAuthService extends OAuthService{        String getoAuthType();    String getAuthorizationUrl();    OAuthUser getOAuthUser(Token accessToken);}

之后,我们将之前所有对OAuthServiceDeractor修改为CustomOAuthService

@Servicepublic class OAuthServices {        @Autowired List<CustomOAuthService> oAuthServiceDeractors;        public CustomOAuthService getOAuthService(String type){        Optional<CustomOAuthService> oAuthService = oAuthServiceDeractors.stream().filter(o -> o.getoAuthType().equals(type))                .findFirst();        if(oAuthService.isPresent()){            return oAuthService.get();        }        return null;    }        public List<CustomOAuthService> getAllOAuthServices(){        return oAuthServiceDeractors;    }}

这样,我们对于第三方框架的重构就完成了。接下来我们来具体实现微信的第三方登录。

WeixinApi

首先,添加WeixinApi,为OAuthService提供进行OAuth验证的各个地址,相关的地址可以在微信登录开发文档中得到,想了解微信第三方登录具体细节的同学可以仔细研读一下该文档。最终的WeixinApi代码如下:

public class WeixinApi extends DefaultApi20 {        private static final String AUTHORIZE_URL = "https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&state=esfadsgsad34fwdef&scope=snsapi_login#wechat_redirect";    private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?grant_type=authorization_code";    @Override    public String getAuthorizationUrl(OAuthConfig config) {        return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()));    }    @Override    public String getAccessTokenEndpoint() {        return ACCESS_TOKEN_URL;    }        @Override    public OAuthService createService(OAuthConfig config){      return new WeixinOAuthService(this, config);    }}

WeixinOAuthService

最后是WeixinOAuthService的实现,除了CustomOAuthService的所定位的方法外,我们还需要重写getAccessToken

public class WeixinOAuthService extends OAuth20ServiceImpl implements CustomOAuthService {        private final DefaultApi20 api;    private final OAuthConfig config;    private final String authorizationUrl;        public WeixinOAuthService(DefaultApi20 api, OAuthConfig config) {        super(api, config);        this.api = api;        this.config = config;        this.authorizationUrl = getAuthorizationUrl(null);    }    @Override    public Token getAccessToken(Token requestToken, Verifier verifier){      OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint());      request.addQuerystringParameter("appid", config.getApiKey());      request.addQuerystringParameter("secret", config.getApiSecret());      request.addQuerystringParameter(OAuthConstants.CODE, verifier.getValue());      if(config.hasScope()) request.addQuerystringParameter(OAuthConstants.SCOPE, config.getScope());      Response response = request.send();      String responceBody = response.getBody();      Object result = JSON.parse(responceBody);      return new Token(JSONPath.eval(result, "$.access_token").toString(), "", responceBody);    }    @Override    public OAuthUser getOAuthUser(Token accessToken) {        OAuthUser oAuthUser = new OAuthUser();        oAuthUser.setoAuthType(getoAuthType());        Object result = JSON.parse(accessToken.getRawResponse());        oAuthUser.setoAuthId(JSONPath.eval(result, "$.openid").toString());        oAuthUser.setUser(new User());        return oAuthUser;    }    @Override    public String getoAuthType() {        return OAuthTypes.WEIXIN;    }    @Override    public String getAuthorizationUrl() {        return authorizationUrl;    }}

配置WeixinOAuthService

最后添加WeixinOAuthService的相关配置:

@Configurationpublic class OAuthConfig {        private static final String CALLBACK_URL = "http://tianmaying.com/oauth/%s/callback";        @Value("${oAuth.weixin.appId}") String weixinAppId;    @Value("${oAuth.weixin.appSecret}") String weixinAppSecret;        @Bean    public CustomOAuthService getSinaOAuthService(){        return (CustomOAuthService) new ServiceBuilder()            .provider(WeixinApi.class)            .apiKey(weixinAppId)            .apiSecret(weixinAppSecret)            .scope("snsapi_login")            .callback(String.format(CALLBACK_URL, OAuthTypes.WEIXIN))            .build();    }    }

修改hosts

与新浪微博一样,修改hosts一遍进行本地调试。

windows系统hosts文件一般在C:\WINDOWS\system32\drivers\etc

mac系统hosts文件地址一般为:/etc/hosts

在hosts文件添加以下一行:

127.0.0.1       tianmaying.com

调试

进入根目录,运行sudo mvn spring-boot:run命令,访问http://tianmaying.com (之前填写应用信息以及修改hosts时所填写的域名,这三个域名必须一致),由于必须通过域名进行访问,所以我们需要监听80端口,运行时需要超级管理员权限。

0 0
原创粉丝点击