1.OAuth 认识
官网:https://oauth.net/2/
OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是OAUTH的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此OAUTH是安全的。oAuth是Open Authorization的简写,目前的版本是2.0版。
2.OAuth 思路/执行流程
Client - 客户端
Resource Owner - 资源拥有者
Authorization Server - 认证服务器
Resource Server - 资源服务器
- (A)用户打开客户端,要求用户给予授权
- (B)用户同意给予客户端授权
- (C)客户端使用获得的授权,向服务器申请令牌
- (D)认证服务器对客户端进行认证,确认无误,同意发放令牌
- (E)客户端使用令牌,向资源服务器申请获取资源
- (F)资源服务器确认令牌无误,同意向客户端开放资源
3.授权方式 OAuth2.0 定义了四种授权方式
授权码模式(authorization code)
授权码模式是功能最完整的,流程最严密的授权模式;
特点就是 通过客户端的后台服务器与服务提供商的认证服务器进行互动;
A - 用户访问客户端,后者将前者导向认证服务器
B - 用户选择是否给予客户端授权
C - 假设用户给予授权,认证服务器将用户导向客户端事先指定的重定向“url”,同时附上一个授权码
D - 客户端收到授权码,附上早先的重定向“url”,向认证服务申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见
E - 认证服务器核对了授权码和重定向“url”,确认无误后,向客户端发送访问令牌(access token)和 更新令牌(refresh token)
简化模式/隐藏式(implicit)
密码模式(resource owner password credentials)
客户端模式(client credentials)
大概演示一下 GitHub 登录,现在大部分都是 微信 QQ 微博 等等,后面在写个微信演示,都是大同小异
首先肯定是申请 clientID 和 clientSecret (GitHub 官网
clientID:应用的唯一标识
clientSecret:clientID 对应的密钥,访问用户资源时用来验证应用的合法性
登陆图标 按钮 前端这块就不写了
code 获取 token
WebServlet("/getToken")
public class GetTokenServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String code = req.getParameter("code");
//发送请求获取token
String clientID = "xxxxxxxxxxxxx";
String clientSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
String url = "https://github.com/login/oauth/access_token?" +
"client_id="+clientID+"&client_secret="+clientSecret+"&code="+code+
"&redirect_uri=http://www.itsource.cn/callback";
//发送请求
String responseStr = HttpClientUtil.doGet(url);
//解析请求参数
Map<String, String> map = HttpClientUtil.responseStrToMap(responseStr);
String token = map.get("access_token");
//根据token获取用户信息
url = "https://api.github.com/user?access_token="+token;
String userStr = HttpClientUtil.doGet(url);
//json转map
Map jsonMap = JSON.parseObject(userStr);
//获取用户名
String loginUser = (String)jsonMap.get("login");
//登录成功后做事情
resp.setContentType("text/html;charset=utf-8");
String html = "<!DOCTYPE html>" +
"<html>" +
"<head>" +
" <title>登录成功</title>" +
" <meta charset=\"utf-8\"/>" +
"</head>" +
"<body>" +
"欢迎登录:"+loginUser+
"</body>" +
"</html>";
resp.getWriter().print("欢迎登录:"+loginUser);
}
回调处理 Servlet
@WebServlet("/callback")
public class CallBackServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取code
String code = req.getParameter("code");
String loginUrl = "/getToken?code="+code;
String html = "<!DOCTYPE html>" +
"<html>" +
"<head>" +
" <title></title>" +
" <meta charset=\"utf-8\"/>" +
"</head>" +
"<body>" +
" <script type=\"text/javascript\">" +
" window.close();"+
" window.opener.location.href ='" + loginUrl+"';"+
" </script>" +
"</body>" +
"</html>";
resp.getWriter().print(html);
}
}