QQ互联Oauth2.0认证测试

我不太喜欢讲原理,喜欢按照应用流程一步步完成一个测试项目,然后掉过头来看原理。

如此。

首先,我们得建一个应用,这无可厚非。

来个网站应用吧!

填写基本信息时,有个网站地址,我们填写一个自己所维护的外部网站页面地址。

在HEAD标签里按照提示,嵌入验证代码,并加以验证。

回调地址填写相应的域名。

示例:

  

在新建的web项目里新加一个配置文件如下:

app_ID = ********
app_KEY = *************************
redirect_URI = http://www.******************.tk/Qqtest4SDK/afterlogin.do
scope = get_user_info,add_topic,add_one_blog,add_album,upload_pic,list_album,add_share,check_page_fans,add_t,add_pic_t,del_t,get_repost_list,get_info,get_other_info,get_fanslist,get_idollist,add_idol,del_ido,get_tenpay_addr
baseURL = https://graph.qq.com/
getUserInfoURL = https://graph.qq.com/user/get_user_info
accessTokenURL = https://graph.qq.com/oauth2.0/token
authorizeURL = https://graph.qq.com/oauth2.0/authorize
getOpenIDURL = https://graph.qq.com/oauth2.0/me

这里的redirect_URI是在oauth2.0认证时调用的地址,必须为有效地址,且为同项目下的,我建一个Servlet对应该请求。

我们访问网站地址(并没有做特殊的处理),默认将跳转到本地的index.jsp,jsp的头部之前已经说过,需要添加先关验证<meta>标签

body部分:

  <center>
          <!-- 测试登陆授权 -->
          <a href="/Qqtest4SDK/login.do"><img src="/Qqtest4SDK/img/qq_login.png" /></a>
    </center>

后端Servlet处理请求:

public class IndexServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/html;charset=utf-8");
        try {
            
            String reUrl =new Oauth().getAuthorizeURL(request);
            
            response.sendRedirect(reUrl);
        } catch (QQConnectException e) {
            e.printStackTrace();
        }
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        doGet(request,  response);
    }
}

这里我们需要了解下Oauth2.0的相关认证,Eclipse market下载安装JadClipse反编译工具.

Oauth2.0:

构造请求(PC):

Step1:获取 Authorization Code

Get方式:

  https://graph.qq.com/oauth2.0/token

参数:

  response_type 固定为code、client_id为appid、redirect_uri 授权成功后callbackURL、state:client端的状态值

public String getAuthorizeURL(ServletRequest request)
            throws QQConnectException {
        String state = RandomStatusGenerator.getUniqueState();
        ((HttpServletRequest) request).getSession().setAttribute(
                "qq_connect_state", state);
        String scope = QQConnectConfig.getValue("scope");
        if ((scope != null) && (!(scope.equals("")))) {
            return getAuthorizeURL("code", state, scope);
        }
        return QQConnectConfig.getValue("authorizeURL").trim() + "?client_id="
                + QQConnectConfig.getValue("app_ID").trim() + "&redirect_uri="
                + QQConnectConfig.getValue("redirect_URI").trim()
                + "&response_type=" + "code" + "&state=" + state;
    }

Step2:通过 Authorization Code获取令牌Access Token:

授权成功后,解析响应信息,获取authorization code及原始的state:

private String[] extractionAuthCodeFromUrl(String url)
            throws QQConnectException {
        if (url == null) {
            throw new QQConnectException("you pass a null String object");
        }
        Matcher m = Pattern.compile("code=(\w+)&state=(\w+)&?").matcher(url);
        String authCode = "";
        String state = "";
        if (m.find()) {
            authCode = m.group(1);
            state = m.group(2);
        }

        return new String[] { authCode, state };
    }

封装信息,并POST请求获取Access Token:

public AccessToken getAccessTokenByRequest(ServletRequest request)
            throws QQConnectException {
        String queryString = ((HttpServletRequest) request).getQueryString();
        if (queryString == null) {
            return new AccessToken();
        }
        String state = (String) ((HttpServletRequest) request).getSession()
                .getAttribute("qq_connect_state");
        if ((state == null) || (state.equals(""))) {
            return new AccessToken();
        }

        String[] authCodeAndState = extractionAuthCodeFromUrl(queryString);
        String returnState = authCodeAndState[1];
        String returnAuthCode = authCodeAndState[0];

        AccessToken accessTokenObj = null;

        if ((returnState.equals("")) || (returnAuthCode.equals(""))) {
            accessTokenObj = new AccessToken();
        } else if (!(state.equals(returnState))) {
            accessTokenObj = new AccessToken();
        } else
            accessTokenObj = new AccessToken(this.client.post(
                    QQConnectConfig.getValue("accessTokenURL"),
                    new PostParameter[] {
                            new PostParameter("client_id", QQConnectConfig
                                    .getValue("app_ID")),
                            new PostParameter("client_secret", QQConnectConfig
                                    .getValue("app_KEY")),
                            new PostParameter("grant_type",
                                    "authorization_code"),
                            new PostParameter("code", returnAuthCode),
                            new PostParameter("redirect_uri", QQConnectConfig
                                    .getValue("redirect_URI")) }, Boolean
                            .valueOf(false)));

        return accessTokenObj;
    }

有了令牌,我们就可以根据令牌获取openid,有了openid我们才可以调用接口。

那么,如何获取openid呢?

Step3:获取Openid

请求地址:https://graph.qq.com/oauth2.0/me

参数  :access_token

Get方式:

private String getUserOpenID(String accessToken) throws QQConnectException {
        String openid = "";
        String jsonp = this.client.get(
                QQConnectConfig.getValue("getOpenIDURL"),
                new PostParameter[] { new PostParameter("access_token",
                        accessToken) }).asString();

        Matcher m = Pattern.compile(""openid"\s*:\s*"(\w+)"").matcher(
                jsonp);

        if (m.find())
            openid = m.group(1);
        else {
            throw new QQConnectException("server error!");
        }
        return openid;
    }

Step4:调用OpenAPI

以get_user_info接口为例:

  https://graph.qq.com/user/get_user_info?access_token=YOUR_ACCESS_TOKEN&oauth_consumer_key=YOUR_APP_ID&openid=YOUR_OPENID

很简单,构造UserInfo 继承自维护access token和openid的父类,新增返回用户信息UserInfoBean的方法:

在方法里请求以上url并封装响应结果json信息即可:

public class UserInfo extends QQConnect {
    private static final long serialVersionUID = -6124397423510235640L;

    public UserInfo(String token, String openID) {
        super(token, openID);
    }

    private UserInfoBean getUserInfo(String openid) throws QQConnectException {
        return new UserInfoBean(this.client.get(
                QQConnectConfig.getValue("getUserInfoURL"),
                new PostParameter[] {
                        new PostParameter("openid", openid),
                        new PostParameter("oauth_consumer_key", QQConnectConfig
                                .getValue("app_ID")),
                        new PostParameter("access_token", this.client
                                .getToken()),
                        new PostParameter("format", "json") }).asJSONObject());
    }

    public UserInfoBean getUserInfo() throws QQConnectException {
        return getUserInfo(this.client.getOpenID());
    }
}
每一步脚印都要扎得深一点!
原文地址:https://www.cnblogs.com/bloodthirsty/p/4110822.html