作者:lly
文章目录
一、授权服务器搭建
这一部分可基于Oauth2协议自由变动,不做详细介绍,可参考网上相应博客,如下链接
二、SuperMap iServer扩展和配置流程
本文基于iServer帮助文档“扩展使用 OAuth2协议的账户”示例修改,主要改动为获取token请求方式改为post,如需使用get请求,可直接在帮助文档示例代码基础上修改,流程为以下几步:1.获取code 2.通过code获取token 3.拿到token获取用户信息 4.在iServer中绑定iServer账户
注:iServer目前只支持授权码方式
2.1 自定义登录方式实现类
package com.supermap.services.rest.resources.impl;
import java.io.*;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import com.supermap.services.security.OAuth2Client;
import com.supermap.services.security.OAuthUserInfo;
import org.apache.commons.io.IOUtils;
import java.net.URISyntaxException;
import org.apache.http.HttpEntity;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;
import java.net.HttpURLConnection;
public class RenRenLoginExtended implements OAuth2Client {
// 人人的 <FONT style="BACKGROUND-COLOR: #0078d7" color=#ffffff>OAuth2</FONT>认证根地址
public static final String OAUTH_URL_RENREN = System.getProperty("OAUTH_RENREN", "http://192.168.15.23:8080");
private static final String GET_CODE_URI_RENREN = OAUTH_URL_RENREN
+ "/oauth/authorize?client_id=%s&response_type=code&redirect_uri=%s&state=%s&display=page";
private static final String GET_TOKEN_BY_CODE_RENREN = OAUTH_URL_RENREN + "/oauth/token?client_id=%s&client_secret=%s&grant_type=authorization_code&code=%s&redirect_uri=%s";
private static final String useridUrl = "http://192.168.15.23:8080/oauth/check_token?token=%s";
private static final String userInfoUrl = "http://192.168.15.23:8080/oauth/check_token?token=%s&client_id=%s&userID=%s";
//获取 <FONT style="BACKGROUND-COLOR: #0078d7" color=#ffffff>OAuth2</FONT>跳转 URI
public String getRedirectURI(String clientID, String state, String redirectUri) {
return String.format(GET_CODE_URI_RENREN, clientID, redirectUri, state);
}
//获取访问 Token
public String getAccesstoken(String clientID, String clientSecret, String code, String redirectUri) throws IOException {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 参数
StringBuffer params = new StringBuffer();
try {
// 字符数据最好encoding以下;这样一来,某些特殊字符才能传过去(如:某人的名字就是“&”,不encoding的话,传不过去)
params.append("client_id=" + URLEncoder.encode(clientID, "utf-8"));
params.append("&");
params.append("client_secret=" + URLEncoder.encode(clientSecret, "utf-8"));
params.append("&");
params.append("code=" + URLEncoder.encode(code, "utf-8"));
params.append("&");
params.append("grant_type=authorization_code");
params.append("&");
params.append("redirect_uri=" + URLEncoder.encode(redirectUri, "utf-8"));
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
// 创建Post请求
HttpPost httpPost = new HttpPost("http://192.168.15.23:8080/oauth/token" + "?" + params);
System.out.println("http://192.168.15.23:8080/oauth/token" + "?" + params);
// 设置ContentType(注:如果只是传普通参数的话,ContentType不一定非要用application/json)
httpPost.setHeader("Content-Type", "application/json;charset=utf8");
// 响应模型
CloseableHttpResponse response = null;
try {
// 由客户端执行(发送)Post请求
response = httpClient.execute(httpPost);
// 从响应模型中获取响应实体
HttpEntity responseEntity = response.getEntity();
System.out.println("响应状态为:" + response.getStatusLine());
if (responseEntity != null) {
System.out.println("响应内容长度为:" + responseEntity.getContentLength());
//System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
JSONObject tokenObj = new JSONObject(EntityUtils.toString(responseEntity));
System.out.println(tokenObj);
return tokenObj.getString("access_token");
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 释放资源
if (httpClient != null) {
httpClient.close();
}
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
// 获取用户 ID,本文示例此方法并没有调用
public String getUserID(String accesstoken) throws IOException {
String useridfourl = String.format(useridUrl, URLEncoder.encode(accesstoken, "utf-8"));
try {
String useridresult = IOUtils.toString(new URI(useridfourl), "utf-8");
JSONObject useridObj = new JSONObject(useridresult);
System.out.println(useridObj);
return useridObj.getString("user_name");
} catch (JSONException e) {
throw new IOException(e);
} catch (URISyntaxException e) {
throw new IOException(e);
}
}
//获取用户信息
public OAuthUserInfo getUserInfo(String token, String clientID, String userID) throws IOException {
String userinfourl = String.format(userInfoUrl, URLEncoder.encode(token, "utf-8"), clientID, userID);
OAuthUserInfo userinforesult = new OAuthUserInfo();
String content = null;
try {
content = IOUtils.toString(new URI(userinfourl), "utf-8");
JSONObject userinfoJson = new JSONObject(content);
//获取图标的url
userinforesult.figureurl = "https://img.alicdn.com/tps/TB1h9xxIFXXXXbKXXXXXXXXXXXX.jpg";
userinforesult.nickName = userinfoJson.getString("user_name");
return userinforesult;
} catch (JSONException e) {
throw new IOException(e);
} catch (URISyntaxException e) {
throw new IOException(e);
}
}
}
将编译后包含 RenRenLoginExtended.class 文件的整个 com 目录拷贝到 SuperMap iServer Web 应用下,即 %SuperMap iServer_HOME%\webapps\iserver\WEB-INF\classes 下(先在该目录下新建 classes 文件夹)或者将打包好的jar包直接解压到当前目录.
2.2 自定义方式的配置extendedOAuth.xml
在产品包根目录 %SuperMap iServer_HOME%webapps/iserver/WEB-INF 下新建一个 extendedOAuth.xml 文件,里面的内容如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<extendedOAuthSettings>
<extendedOAuthSetting>
<loginType>RENREN</loginType>
<oAuth2ClientClass>com.supermap.services.rest.resources.impl.RenRenLoginExtended</oAuth2ClientClass>
</extendedOAuthSetting>
</extendedOAuthSettings>
其中为遵循 OAuth2 协议的第三方登录方式扩展实现配置集合,可以包含多个标签。每个标签对应一种遵循 OAuth2 协议的第三方登陆方式扩展实现配置,标签中的内容对应于 ExtendedOAuthSetting 中的配置项:
:扩展后支持的登录类型,这里是“RENREN”,可自定义。
:扩展后登录类型的具体实现类,这里为“人人网账号登陆”方式对应的实现类。
2.3 配置 iserver-system.xml
在产品包根目录 %SuperMap iServer_HOME%webapps/iserver/WEB-INF 下的 iserver-system.xml 文件的根节点中添加如下内容:
<oAuthConfigs>
<oAuthConfig>
<id>1</id>
<enabled>true</enabled>
<loginType>RENREN</loginType>
<buttonText>自己账号登陆</buttonText>
<clientSecret>secret</clientSecret>
<clientID>client</clientID>
<redirectDomain>192.168.15.23</redirectDomain>
<loginIcon>renren.png</loginIcon>
</oAuthConfig>
</oAuthConfigs>
其中为遵循 OAuth2 协议的第三方登陆方式 配置项集合,可以包含多个标签。每个标签对应一种登陆方式的配置,中的内容对应于 OAuthConfig 中的配置项:
:遵循 OAuth2 协议的第三方登陆方式对应的配置 ID 。
:是否启用遵循 OAuth2 协议的第三方登陆方式。
:遵循 OAuth2 协议的第三方登陆方式,这里为“RENREN”。
:在登录界面显示的登录按钮名称,这里为“自己账号登陆”。
:申请应用时分配的 AppSecret ,这里为自己建的库中oauth_client_details表中的client_secret字段记录值。
:申请应用时分配的 Appkey ,这里为自己建的库中oauth_client_details表中的client_id字段记录值。
:申请应用时填写的回调域名,这里为客户端ip“192.168.15.23”。
:在登录界面显示的登录图片标识,这里为“renren.png”。该图片必须放于 %SuperMap iServer_HOME%webapps/iserver/WEB-INF/lib 目录下的 iserver-all.jar 的 ./staticFiles/img 文件夹下,也可使用在线图片,无图片不影响正常使用。
如果值为 QQ 或 Weibo ,则此标签可省略。
三、验证
配置完成后重启iServer,在登录页面点击三方登录
输入Oauth2账号
勾选允许访问资源
首次登录会要求绑定iServer账户
绑定成功后会自动跳转到服务列表页面
后续该账户再进行登录时,就会直接登录跳转了,无需再做操作。