应用场景
web应用通过人人网登录授权实现第三方登录。操作步骤
1 注册成为人人网开放平台开发者/developers/devinfo2 准备一个可访问的域名,如 3 创建网页应用,配置必要信息,其中包括根域名、图标信息4 获取应用appID、appKey进行开发登录流程
采用server-side方式实现登录授权,流程如下流程描述1 server端页面跳转到登录授权页面(Authorization code方式) 2 回调获得code 3 置换accessToken,同时也得到uid、用户资料信息 4 同步用户信息并登录OAuth2.0 采用Authorization code方式将更为可靠、安全。 更多信息可参考人人网开放平台wiki: http://wiki./wiki/Authentication#.E6.9C.8D.E5.8A.A1.E7.AB.AF.E6.8E.88.E6.9D.83
案例实战
本地开发环境准备
修改hosts文件将映射到127.0.0.1;本地服务器以80端口启动,windows下可能会出现80端口被系统进程占用的情况,解决方法可参考/littleatp/p/4414578.html本地服务器启动后,以的域名进行访问,在登录授权时可通过域名验证这一步前端登录跳转页面
<html><head><title>人人网登录跳转</title><script src="/js/jquery/1.7.2/jquery.min.js" type="text/javascript"></script><script type="text/javascript">//应用的APIKEYvar apiKey = "3ce9cb1e264f4e93b1f38807be66e629";//成功授权后的回调地址var redirectUrl = "@@{openapi.Renrens.callback()}";var authorizeUrl = "/oauth/authorize?"var queryParams = ['client_id=' + apiKey,'redirect_uri=' + redirectUrl,'response_type=code'];var url = authorizeUrl + queryParams.join('&');//打开授权登录页面 window.location.href= url;</script></head><body></body></html>
功能描述页面在打开时直接跳转到人人网登录授权页面,此后授权成功后将回调至redirect_uri
server端处理回调,同步信息
授权回调的页面处理/*** 授权回调** @param code* @param error*/public static void callback(String code) {if (!StringUtils.isEmpty(code)) {error("授权失败");}// 根据code换取accesstoken,包括用户信息// ...String callbackUrl = RouteContext.getUrl("openapi.Renrens.callback", Collections.EMPTY_MAP,true);RenrenToken token = RenApi.getTokenInfo(code, callbackUrl);if (token == null) {error("授权失败:无法获取连接系统");}render(code, token);}
数据对象RenrenToken类
/*** 返回token数据对象* * <pre>** { * "token_type":"bearer",* "expires_in":2595096,* "refresh_token":"127021|0.KAS3b8doSitHk6RLDtitb2VY8PjktTRA.229819774.1376381303243",* "user":{*"id":229819700,*"name":"二小姐",*"avatar":[* { "type":"avatar",* "url":"/photos/hdn121/0805/2055/h_head_KFTQ_d536000000d0111b.jpg"* },* { "type":"tiny",* "url":"/photos/hdn221/0805/2055/tiny_jYQe_ec4300051e7a113f.jpg"* },* { "type":"main",* "url":"/photos/hdn121/0805/2055/h_main_ksPJ_d536000000d0111b.jpg"},* { "type":"large",* "url":"/photos/hdn121/0805/2055/h_large_yxZz_d536000000d0111b.jpg"* }*]* },* "access_token":"127066|6.08718aa138db0578dda3250f33bads6e.2592000.1378976400-229819774"* "scope":"read_user_feed read_user_album",* </pre>* * @author littleatp* @createDate 4月14日* */public class RenrenToken {public String token_type;public int expires_in;public String refresh_token;public String access_token;public String scope;public RenrenUser user;}
RenrenUser类
/*** 人人网用户信息* * <pre>* "user":{*"id":229819700,*"name":"二小姐",*"avatar":[* { "type":"avatar",* "url":"/photos/hdn121/0805/2055/h_head_KFTQ_d536000000d0111b.jpg"* },* { "type":"tiny",* "url":"/photos/hdn221/0805/2055/tiny_jYQe_ec4300051e7a113f.jpg"* },* { "type":"main",* "url":"/photos/hdn121/0805/2055/h_main_ksPJ_d536000000d0111b.jpg"},* { "type":"large",* "url":"/photos/hdn121/0805/2055/h_large_yxZz_d536000000d0111b.jpg"* }*]* },* </pre>* * @author littleatp* @createDate 4月14日* */public class RenrenUser {public long id;public String name;public List<RenrenAvatar> avatar;public String getAvatarUrl() {if (avatar == null || avatar.isEmpty()) {return "";}return avatar.get(0).url;}public static class RenrenAvatar {public String type;public String url;}}
RenApi功能实现
/*** 人人网API* * <pre>* 登录流程:* * 1 前端跳转人人网授权(code方式)* 2 回调获得authorize code* 3 通过code换取access_token* 4 获得token及用户信息* * 参考文档:*http://wiki./wiki/Authentication* </pre>* * * @author littleatp* @createDate 4月10日* */public class RenApi {public static String apiKey = "xxx";public static String secretKey = "xxx";public static String baseUrl = "/oauth";protected static final String URL_GET_TOKEN = baseUrl + "/token?grant_type=authorization_code"+ "&client_id=%s&client_secret=%s&code=%s&redirect_uri=%s";protected static final long ACCESS_TIMEOUT = 15;protected static final String DEF_APP_TOKEN_EXPIRE = "3h";/*** 获取token信息* * <pre>*http://wiki./wiki/Authentication#.E5.AE.A2.E6.88.B7.E7.AB.AF.E6.8E.88.E6.9D.83* 返回token的同时也附带了用户信息* * 调用地址:*/oauth/token* * 参数* grant_type:使用Authorization Code 作为Access Grant时,此值固定为“authorization_code”;* client_id:在开发者中心注册应用时获得的API Key;* client_secret:在开发者中心注册应用时获得的Secret Key。Secret Key是应用的保密信息,请不要将其嵌入到服务端以外的代码里;* redirect_uri:必须与获取Authorization Code时传递的“redirect_uri”保持一致;* code:上述过程中获得的Authorization Code。* * 返回结果如下:* { * "token_type":"bearer",* "expires_in":2595096,* "refresh_token":"127021|0.KAS3b8doSitHk6RLDtitb2VY8PjktTRA.229819774.1376381303243",* "user":{*"id":229819700,*"name":"二小姐",*"avatar":[* { "type":"avatar",* "url":"/photos/hdn121/0805/2055/h_head_KFTQ_d536000000d0111b.jpg"* },* { "type":"tiny",* "url":"/photos/hdn221/0805/2055/tiny_jYQe_ec4300051e7a113f.jpg"* },* { "type":"main",* "url":"/photos/hdn121/0805/2055/h_main_ksPJ_d536000000d0111b.jpg"},* { "type":"large",* "url":"/photos/hdn121/0805/2055/h_large_yxZz_d536000000d0111b.jpg"* }*]* },* "access_token":"127066|6.08718aa138db0578dda3250f33bads6e.2592000.1378976400-229819774"* "scope":"read_user_feed read_user_album",* }* * 错误返回:* {* "error": "invalid_grant",* "error_code": 4* "error_description": "Invalid authorization code: 9OCQp3IzRcwtSRPKOEUKiRRsz9SUNgdE"* }*http://wiki./wiki/%E9%94%99%E8%AF%AF%E5%93%8D%E5%BA%94* </pre>* * @param accessToken* @return*/public static RenrenToken getTokenInfo(String code, String callbackUrl) {if (StringUtils.isEmpty(code)) {return null;}String url = String.format(URL_GET_TOKEN, apiKey, secretKey, code, callbackUrl);String resultString = DefaultHttp.get(url, ACCESS_TIMEOUT, GlobalConstants.UTF_8);Logger.debug("[sso-renren]gettoken. use url '%s'", url);RenrenToken token = JsonUtil.fromJson(resultString, RenrenToken.class);if (token == null || StringUtils.isEmpty(token.access_token)) {Logger.debug("[sso-renren]get token failed, with result of '%s'", resultString);return null;}Logger.debug("[sso-renren]get token success, with result of '%s'", resultString);return token;}}