OAuth2第三方登入

晦若晨曦發表於2017-12-14

第三方登入是現在的應用、網站很常用的功能。能夠提高使用者註冊率,簡化登入流程,充分利用各大門戶的使用者資源。

最近的工作中涉及到了第三方登入的功能,為了方便日後使用,將此部分功能進行了簡單的封裝。

##OAuth2

oauth2是當前主流的第三方授權協議。通過此協議呼叫可以獲取到服務提供方的使用者各種詳細資訊,呼叫提供方的API介面實現各種功能。

OAuth2的第三方登入認證流程主要分為三步: ####1、帶領使用者訪問認證url 提供給使用者,或者轉發至提供方的認證URL,並指定一個回撥介面,使用者進行授權之後,服務提供方會告知回撥介面,進行下一步操作

####2、通過code獲取access_token 服務提供方會向回撥介面傳遞一個code,呼叫指定的API,可以使用此code獲取一個access_token,這是授權的證據,使用此token可以呼叫服務提供商的各種介面

####3、使用access_token獲取使用者資訊 完成授權後,使用此token可以獲取使用者的賬號,暱稱,id,頭像等各種資訊。

##實現: 為了統一呼叫,首先封裝了一個抽象類:

public abstract class OAuth2 {

    public static final String QQ = "qq";
    public static final String SINA = "sina";
    public static final String WECHAT = "wechat";

    public static OAuth2 getOAuthTool(String company){
        switch(company){
            case QQ:
                return new QQOauth2();
            case SINA:
                return new SinaOAuth2();
            case WECHAT:
                return new WechatOAuth2();
        }
        return null;
    }

    public abstract JSONObject getAccessToken(String code);

    public abstract JSONObject getUser(String access_token, String oid);

    public abstract String getAuthUrl();

}
複製程式碼

抽象類中提供了一個工廠方法,可見我已經實現了QQ,新浪微博和微信的第三方登入功能。根據不同的引數就可以返回不同的例項。

下面以微信登入為例說明一下實現:

public class WechatOAuth2 extends OAuth2{

    static String client_ID = "wxxxxxxxxxxxxxx";
    static String client_SERCRET = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
    static String redirect_URI = "http://www.thinkool.com.cn/oauth/signin";
    /*----------------------------Oauth介面--------------------------------------*/


    @Override
    public JSONObject getAccessToken(String code) {
        Map<String,Object> objectMap
                = new HashMap<>();
        objectMap.put("client_id", client_ID);
        objectMap.put("client_secret", client_SERCRET);
        objectMap.put("grant_type", "authorization_code");
        objectMap.put("code", code);
        objectMap.put("redirect_uri", redirect_URI);
        //
        String url =
                "https://api.weixin.qq.com/sns/oauth2/access_token?grant_type=authorization_code&"+
                        "appid="+client_ID+
                        "&secret="+client_SERCRET+
                        "&code="+code+
                        "&state="+"wechat"+"&redirect_uri="+redirect_URI;
        try {

            //access_token & openid
            return HttpUtil.get(url);
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public JSONObject getUser(String access_token,String oid) {
        String getuser = "https://api.weixin.qq.com/sns/userinfo?"+
                "access_token="+access_token+
                "&openid="+oid;
        JSONObject user = null;
        try {
            user = HttpUtil.get(getuser);
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
//        user.put("openid",oid);
        //openid & nickname & headimgurl
        System.out.println(user);
        return user;
    }

    @Override
    public String getAuthUrl() {
        return "https://open.weixin.qq.com/connect/qrconnect" +
                "?appid="+ client_ID.trim() +
                "&redirect_uri="+ redirect_URI.trim()
                + "&response_type=code" + "&state=wechat" +"&scope=snsapi_login";
    }
}
複製程式碼

首先getAuthUrl方法完成第一步,拼寫一個認證字串,並引導使用者訪問以完成授權。

getAccessToken方法完成第二步,通過返回的code獲取到一個access_token。

getUser方法完成第三部,通過獲取到的access_token呼叫介面以獲取使用者的詳細資訊。

##其他事項

####1、此實現依賴於阿里的開源Json庫fastjson ####2、不同的提供方的呼叫流程不完全一致。 微信和新浪的第一步授權提供了此使用者的openid,在呼叫時直接使用access_token和openid就可以獲取使用者的詳細資訊。QQ的授權則沒有提供openid,需要進行一步獲取openid,才能使用openid獲取到使用者的詳細資訊。

相關文章