Extend to use accounts which follow OAuth2 protocol

Feedback


SuperMap iServer provides the OAuth2Client interface for third-party login ways extensions that follow the OAuth2 protocol. Such third-party login ways include QQ, Sina Weibo, etc. Among them, QQ and Sina Weibo are two third-party login ways built in SuperMap iServer that follow the OAuth2 protocol.

Introduction to the OAuth2Client interface

The com.supermap.services.security.OAuth2Client interface has the following methods:

This method is used to get the OAuth jump URI.

This method is used to obtain the access Token.

This method is used to obtain the user ID.

The method is used for obtaining user information.

This method is used for logout.

Extension and configuration process

We implement a simple extension to illustrate the extension process of third-party login ways following the OAuth2 protocol, taking the extension of "weibo account login" as an example.

1. "weibo account login" implementation class

Implemented the WeiboOAuth2ClientExtended class, inheriting from the OAuth2Client interface The code is as follows:

package com.supermap.services.security;

import com.alibaba.fastjson.JSON;

import com.alibaba.fastjson.JSONObject;

import org.apache.commons.io.IOUtils;

import org.apache.commons.lang3.StringUtils;

import org.apache.http.HttpEntity;

import org.apache.http.HttpResponse;

import org.apache.http.client.entity.UrlEncodedFormEntity;

import org.apache.http.client.methods.HttpPost;

import org.apache.http.impl.client.DefaultHttpClient;

import org.apache.http.message.BasicNameValuePair;

import org.apache.http.protocol.HTTP;

import org.apache.http.util.EntityUtils;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import java.io.IOException;

import java.io.UnsupportedEncodingException;

import java.net.URI;

import java.net.URISyntaxException;

import java.util.ArrayList;

import java.util.List;

public class WeiboOAuth2ClientExtended implements OAuth2Client {

//weibo authentication root address

    private static final String OAUTH_URL_WEIBO = System.getProperty("OAUTH_WEIBO", "https://api.weibo.com");

    private static final String GET_CODE_URI_WEIBO = OAUTH_URL_WEIBO + "/oauth2/authorize?client_id=%s&response_type=code&redirect_uri=%s&state=%s";

    private static final String USERINFO_URL_PATTERN = OAUTH_URL_WEIBO + "/2/users/show.json?access_token=%s&source=%s&uid=%s";

    private static final String EMAIL_URL_PATTERN = OAUTH_URL_WEIBO + "/2/account/profile/email.json?access_token=%s&source=%s";

    private static final String GET_TOKEN_BY_CODE_WEIBO = OAUTH_URL_WEIBO + "/oauth2/access_token";

    private static final String REVOKE_WEIBO = OAUTH_URL_WEIBO + "/oauth2/revokeoauth2?access_token=%s";

    private String userID;

//Get the jump URI

    @Override

    public String getRedirectURI(String clientID, String state, String redirectUri) {

        return String.format(GET_CODE_URI_WEIBO, clientID, redirectUri, state);

   }

//Get Access Token

    @Override

    public String getAccesstoken(String clientID, String clientSecret, String code, String redirectUri) {

        String tokenUrl = GET_TOKEN_BY_CODE_WEIBO;

        List<BasicNameValuePair> nvps = new ArrayList<BasicNameValuePair>();

        nvps.add(new BasicNameValuePair("client_id", clientID));

        nvps.add(new BasicNameValuePair("client_secret", clientSecret));

        nvps.add(new BasicNameValuePair("grant_type", "authorization_code"));

        nvps.add(new BasicNameValuePair("code", code));

        nvps.add(new BasicNameValuePair("redirect_uri", redirectUri));

        String tokenResult = getContentByMethodPost(tokenUrl, nvps);

        if (StringUtils.isBlank(tokenResult)) {

            return null;

       }

        JSONObject tokenObj = JSON.parseObject(tokenResult);

        userID = tokenObj.getString("uid");

        return tokenObj.getString("access_token");

   }

//Get the user ID

    @Override

    public String getUserID(String accessToken) {

        return userID;

   }

//Get user information

    @Override

    public OAuthUserInfo getUserInfo(String token, String clientID, String userID) throws IOException {

        String url = String.format(USERINFO_URL_PATTERN, token, clientID, userID);

        OAuthUserInfo result = new OAuthUserInfo();

        String content;

        try {

            content = IOUtils.toString(new URI(url), "utf-8");

            JSONObject json = JSON.parseObject(content);

            if (json != null) {

                result.figureurl = json.getString("profile_image_url");

                result.nickName = json.getString("nickname");

                result.name = json.getString("name");

                result.email = getEmail(token, clientID);

           }

            return result;

       } catch (IOException | URISyntaxException e) {

            throw new IOException(e);

       }

   }

    private String getEmail(String token, String clientId) throws IOException {

        try {

            String url = String.format(EMAIL_URL_PATTERN, token, clientId);

            String content = IOUtils.toString(new URI(url), "utf-8");

            if (StringUtils.isBlank(content)) {

                return StringUtils.EMPTY;

           }

            int startIndex = StringUtils.indexOf(content, '[');

            int endIndex = StringUtils.indexOf(content, ']');

            content = StringUtils.substring(content, startIndex + 1, endIndex);

            JSONObject json = JSON.parseObject(content);

            if (json != null) {

                return json.getString("email");

           }

       } catch (IOException | URISyntaxException e) {

            throw new IOException(e);

       }

        return StringUtils.EMPTY;

   }

    private String getContentByMethodPost(String url, List<BasicNameValuePair> nvps) {

        HttpPost httpPost = new HttpPost(url);

        try {

            httpPost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));

       } catch (UnsupportedEncodingException e) {

            return null;

       }

        DefaultHttpClient httpClient = new DefaultHttpClient();

        try {

            HttpResponse httpResponse = httpClient.execute(httpPost);

            if (httpResponse.getStatusLine().getStatusCode() == 200) {

                HttpEntity entity = httpResponse.getEntity();

                return EntityUtils.toString(entity, HTTP.UTF_8);

           }

       } catch (IOException ignore) {

       } finally {

            IOUtils.closeQuietly(httpClient);

       }

        return null;

   }

//Log out. Only the access_token callback interface of Weibo is implemented here. The user can also redirect to the logout address of Weibo. The specific code has been noted.

    @Override

    public void logout(ServletRequest request, ServletResponse response, String accessToken) throws IOException {

        String url = String.format(REVOKE_WEIBO, accessToken);

        try {

            // Call to retract access _ token interface

            IOUtils.toString(new URI(url), "utf-8");

            // Redirect logout to certificate authority, destroy Cookies

            // ((HttpServletResponse) response).sendRedirect(LOGOUT_WEIBO);

       } catch (URISyntaxException e) {

            throw new IOException(e);

       }

   }

}

Copy the entire com directory containing the WeiboOAuth2ClientExtended.class file after compilation to the SuperMap iServer web application, under %SuperMap iServer HOME%\webapps\iserver\WEB-INF\classes (first create a new classes folder in this directory)

2. Configuration of "weibo account login" mode

Create a new extendedOAuth.xml file in the root directory of the product package %SuperMap iServer HOME%/webapps/iServer/WEB-INF, with the following contents:

<?xml version="1.0" encoding="UTF-8"?>

<extendedOAuthSettings>

     <extendedOAuthSetting>

           <loginType>WEIBO_EXTENDED</loginType>   

           <oAuth2ClientClass>com.supermap.services.security.WeiboOAuth2ClientExtended</oAuth2ClientClass>

      </extendedOAuthSetting>

</extendedOAuthSettings>

The <extendedOAuthSettings> is a third-party login ways extension implementation configuration set that complies with the OAuth2 protocol, and can contain multiple <extendedOAuthSettings> tags. Each <extendedOAuthSettings> tag corresponds to a type of compliance. The third-party login mode of the OAuth2 protocol is configured by extension, and the content in the < extendedOAuthSetting > label corresponds to the Extended OAuthSetting Configuration items in:

Add the following content to the root node server of the iserver-system.xml file in the product package root directory %SuperMap iServer HOME%/webapps/iServer/WEB-INF

<server>

     ...

    <oAuthConfigs>       

        <oAuthConfig>           

            <id>1</id>              

            <enabled>true</enabled>              

            <loginType>WEIBO_EXTENDED</loginType>   

            <buttonText>微博账号登陆</buttonText>             

            <clientID>YOUR_CLIENT_ID</clientID>             

            <clientSecret>YOUR_CLIENT_SECRET</clientSecret>              

            <redirectDomain>iserver.supermap.com</redirectDomain>

            <roleMapping>{"role_admin":["ADMIN"]}</roleMapping>            

            <loginIcon>weibo.png</loginIcon>       

        </oAuthConfig>   

    </oAuthConfigs>   

    <!--<oAuthMetas>

        <oAuthMeta><meta property="qc:admins" content="4323423424235" /></oAuthMeta>

    </oAuthMetas>-->

</server>

OAuthConfig is a set of third-party login configuration items that comply with the OAuth2 protocol and can contain multiple oAuthConfig tags. Each oAuthConfig tag corresponds to a login method configuration, and the content in oAuthConfig corresponds toOAuthConfig:

The < oAuthMetas > tag represents the meta information used to validate the website address (to be added to the front page HTML in the HEAD tag of the code), the metadata is not required for the extension "WEIBO account login" mode, and the tag has been commented out in this time.

3. View the extension result

When the above steps are completed, it means that the "WEIBO account login" method has been successfully added. On the third-party login configuration page (http://iserver.supermap.com:8090/iserver/manager/security/oauthconfig) , you can view the configuration information of the login method, which is corresponding to the configuration item < oAuthConfig > in the label. Visit the login page of iPortal, iServer or iEdge, you can see that the "weibo account login" button is added on the login page. Click this button to realize WEIBO account login. For more information about the use of third-party login ways that follow the OAuth2 protocol, see: Use of third-party login ways.