目前OAuth 2.0 认证有五种方式,见官方文档:http://www.rfcreader.com/#rfc6749
授权码模式(Authorization Code Grant)
流程图
说明:
1,认证服务器是一个业务无关的系统;
2,code就是授权码,只能使用一次;
3,token 在有效期内可以无限次使用
场景化讲解-下单
场景:A 公司旗下有很多 web 产品,同时还有一个应用商店(类似京东)负责售卖这些软件产品,下面以用户进入应用商店购买产品的流程着手。
- 应用商店通过浏览器尝试获取下单页;
- 应用商店后台鉴权,发现没有登录(应用商店后台实际会调用认证服务器,比如校验 access tokensh是否有效);
- 跳转到登录页面;(对应上图(A))
- 用户通过浏览器输入用户名,密码等方式进行授权(此时会调用认证服务器接口);(对应上图(B))
- 认证服务器返回临时 code 给浏览器;(对应上图(C))
- 应用商店拿临时 code 去调用认证服务器接口,换取 access token;(对应上图(D))
- 认证服务器返回 access token给应用商店;(对应上图(E))
- 应用商店把 access token 缓存下来。
- 后续应用商店调用业务系统(比如下单接口,订单查询接口)接口均带上 access token;
场景化讲解-微信公众号授权
现在很多微商系统接入了微信公众号,通过微信公众号售卖产品,那么它们是如何获取用户信息的呢?
我们在关注某个商店性质的微信公众号时,经常会弹出如下对话框,要求我们授权
图2-1
用户点击上述界面中的"允许",对应的操作是“"授权码模式"的(B)-- User authenticates:
具体流程如下:
- 某微信公众号B 访问用户信息,用于下单支付(实际需要用户的 openid);
- 见图2-1,微信弹框,要求用户授权;
- 用户点击"允许"授权,某微信公众号B才能获取到临时 code;
- 某微信公众号B拿临时 code调用微信鉴权接口获取 access token 或 openid;
实例3-对接钉钉通讯录实现登录
免登流程
第二步:用户授权
授权成功获取code
{"content":"code=4d9954574c32afafd9xxx3c34b414aa&state=STATE","errorLevel":0,"success":true}
code 值为:4d9954574c32afafd9xxx3c34b414aa
授权测试地址
dingtalk://dingtalkclient/page/link?url=https%3A%2F%2Fh5.dingtalk.com%2Fliveeasylogin%2Findex.html%23%2Findex%3Fappid%3Ddingoaemockdlfr66612%26response_type%3Dcode%26scope%3Dsnsapi_auth%26state%3DSTATE%26redirect_uri%3Dhttp%253A%252F%252Floca77host%253A7001%252Fapi%252Ftest%252FtestCode.json%3fddtab%3dtrue
code有什么用?
- 可以获取用户信息;
- 可以获取access_token
获取用户信息
//获取用户信息
DefaultDingTalkClient client = new DefaultDingTalkClient(DingTalkConstants.URL_GET_USER_INFO_BY_CODE);
OapiSnsGetuserinfoBycodeRequest request = new OapiSnsGetuserinfoBycodeRequest();
request.setTmpAuthCode(requestAuthCode);
request.setHttpMethod(HttpMethod.POST.toString());
OapiSnsGetuserinfoBycodeResponse response;
try {
response = client.execute(request, dingTalkProperties.getAppid(), dingTalkProperties.getAppsecret());
} catch (ApiException e) {
logger.error("accessToken:{0}, url:{1}", "", DingTalkConstants.URL_GET_USER_INFO_BY_CODE, e);
return null;
}
LoginedUser loginedUser = null;
if (response.isSuccess() && null != response.getUserInfo()) {
OapiSnsGetuserinfoBycodeResponse.UserInfo userInfo = response.getUserInfo();
获取access_token
略