要实现OAuth服务端,就得先理解客户端的调用流程,服务提供商实现可能也有些区别,实现OAuth服务端的方式很多,具体可能看 http://oauth.net/code/

各语言的实现有(我使用了Apache Oltu):

实现主要涉及参数配置如下:
授权码设置(code)
第三方通过code进行获取 access_token的时候需要用到,code的超时时间为10分钟,一个code只能成功换取一次access_token即失效。
授权作用域(scope)
作用域代表用户授权给第三方的接口权限,第三方应用需要向服务端申请使用相应scope的权限后,经过用户授权,获取到相应access_token后方可对接口进行调用。
令牌有效期(access_token)
access_token是调用授权关系接口的调用凭证,由于access_token有效期(目前为2个小时)较短,当access_token超时后,可以使用refresh_token进行刷新,access_token刷新结果有两种:
    1. 若access_token已超时,那么进行refresh_token会获取一个新的access_token,新的超时时间;
    2. 若access_token未超时,那么进行refresh_token不会改变access_token,但超时时间会刷新,相当于续期access_token。
refresh_token拥有较长的有效期(30天),当refresh_token失效的后,需要用户重新授权。

项目介绍

项目结构如下:
AuthzController:获取授权码
TokenController:获得令牌
ResourceController:资源服务
ClientController:客户端

基础代码放到github:https://github.com/zhouyongtao/homeinns-web

确保项目8080端口运行,可以手动调试

获得授权码
http://localhost:8080/oauth2/authorize?client_id=fbed1d1b4b1449daa4bc49397cbe2350&response_type=code&redirect_uri=http://localhost:8080/oauth_callback
获得令牌(POST)
http://localhost:8080/oauth2/access_token?client_id=fbed1d1b4b1449daa4bc49397cbe2350&client_secret=fbed1d1b4b1449daa4bc49397cbe2350&grant_type=authorization_code&redirect_uri=http://localhost:8080/oauth_callback&code={code}

客户端

也可以使用如下客户端测试代码,访问 http://localhost:8080/client 测试

/**
* Created by Irving on 2014/11/24.
* OAuth2 客户端实现
*/
@Controller
@RequestMapping("/client")
public class ClientController { private static Logger logger = LoggerFactory.getLogger(ClientController.class);
/*
response_type:表示授权类型,必选项,此处的值固定为"code"
client_id:表示客户端的ID,必选项
redirect_uri:表示重定向URI,可选项
scope:表示申请的权限范围,可选项
state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值
*/
/**
* 获得授权码
* @return
*/
@RequestMapping(method = RequestMethod.GET)
public String client() {
try {
OAuthClientRequest oauthResponse = OAuthClientRequest
.authorizationLocation(ConstantKey.OAUTH_CLIENT_AUTHORIZE)
.setResponseType(OAuth.OAUTH_CODE)
.setClientId(ConstantKey.OAUTH_CLIENT_ID)
.setRedirectURI(ConstantKey.OAUTH_CLIENT_CALLBACK)
.setScope(ConstantKey.OAUTH_CLIENT_SCOPE)
.buildQueryMessage();
return "redirect:"+oauthResponse.getLocationUri();
} catch (OAuthSystemException e) {
e.printStackTrace();
}
return "redirect:/home";
} /*
grant_type:表示使用的授权模式,必选项,此处的值固定为"authorization_code"
code:表示上一步获得的授权码,必选项。
redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致
client_id:表示客户端ID,必选项
*/
/**
* 获得令牌
* @return oauth_callback?code=1234
*/
@RequestMapping(value = "/oauth_callback" ,method = RequestMethod.GET)
public String getToken(HttpServletRequest request,Model model) throws OAuthProblemException {
OAuthAuthzResponse oauthAuthzResponse = null;
try {
oauthAuthzResponse = OAuthAuthzResponse.oauthCodeAuthzResponse(request);
String code = oauthAuthzResponse.getCode();
OAuthClientRequest oauthClientRequest = OAuthClientRequest
.tokenLocation(ConstantKey.OAUTH_CLIENT_ACCESS_TOKEN)
.setGrantType(GrantType.AUTHORIZATION_CODE)
.setClientId(ConstantKey.OAUTH_CLIENT_ID)
.setClientSecret(ConstantKey.OAUTH_CLIENT_SECRET)
.setRedirectURI(ConstantKey.OAUTH_CLIENT_CALLBACK)
.setCode(code)
.buildQueryMessage();
OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient()); //Facebook is not fully compatible with OAuth 2.0 draft 10, access token response is
//application/x-www-form-urlencoded, not json encoded so we use dedicated response class for that
//Custom response classes are an easy way to deal with oauth providers that introduce modifications to
//OAuth 2.0 specification //获取access token
OAuthJSONAccessTokenResponse oAuthResponse = oAuthClient.accessToken(oauthClientRequest, OAuth.HttpMethod.POST);
String accessToken = oAuthResponse.getAccessToken();
String refreshToken= oAuthResponse.getRefreshToken();
Long expiresIn = oAuthResponse.getExpiresIn();
//获得资源服务
OAuthClientRequest bearerClientRequest = new OAuthBearerClientRequest(ConstantKey.OAUTH_CLIENT_GET_RESOURCE)
.setAccessToken(accessToken).buildQueryMessage();
OAuthResourceResponse resourceResponse = oAuthClient.resource(bearerClientRequest, OAuth.HttpMethod.GET, OAuthResourceResponse.class);
String resBody = resourceResponse.getBody();
logger.info("accessToken: "+accessToken +" refreshToken: "+refreshToken +" expiresIn: "+expiresIn +" resBody: "+resBody);
model.addAttribute("accessToken", "accessToken: "+accessToken + " resBody: "+resBody);
return "oauth2/token";
} catch (OAuthSystemException ex) {
logger.error("getToken OAuthSystemException : " + ex.getMessage());
model.addAttribute("errorMsg", ex.getMessage());
return "/oauth2/error";
}
}
}

Refer:
https://cwiki.apache.org/confluence/display/OLTU/Index

https://open.weixin.qq.com/cgi-bin/readtemplate?t=resource/app_wx_login_tmpl&lang=zh_CN#faq

最新文章

  1. Theano入门神经网络(三)
  2. C#实现php的hash_hmac函数
  3. hdu5047 找规律+欧拉公式
  4. C#析构函数与垃圾回收
  5. __get,__set
  6. 洛谷P2726 阶乘 Factorials
  7. Selenium2学习-036-WebUI自动化实战实例-034-JavaScript 在 Selenium 自动化中的应用实例之六(获取 JS 执行结果返回值)
  8. HDU-4614 Vases and Flowers (线段树区间更新)
  9. Swift Tips - Array 类型
  10. WAPI
  11. ZOJ --- 3516 Tree of Three
  12. Linux 权限基础说明
  13. Linux,Unix各种版本的操作系统在线安装软件命令
  14. wwwtyro/cellophane
  15. 05 Training versus Testing
  16. python中map()函数用法
  17. 【20180111】【物流FM专访】贝业新兄弟李济宏:我们是如何做到大件家居B2C物流第一的?
  18. HTML辅助方法
  19. R语言中的横向数据合并merge及纵向数据合并rbind的使用
  20. windows 2008 r2 不能启用网络发现

热门文章

  1. Apache 2.4.28的安装
  2. 2.1.6synchronized锁重入
  3. 1.8.3suspend与resume方法的缺点--不同步
  4. Ng第十三课:聚类(Clustering)
  5. 你可能不知道的Shell
  6. SSM_CRUD新手练习(6)分页后台控制器编写
  7. 我们学习Java今后的发展前景
  8. day04_雷神_函数
  9. inline&friend&操作符重载
  10. Android-Kotlin-印章类