点击开始使用时调用
1@RequestProcessing(value = "/login/redirect", method = HttpMethod.GET)
2 public void redirectAuth(final RequestContext context) {
3 // 从当前域里拿到站点地址
4 String referer = context.param("referer");
5 if (StringUtils.isBlank(referer)) {
6 referer = Latkes.getServePath();
7 }
8 // 生成一个16位随机的东西然后跟入站点地址
9 String state = RandomStringUtils.randomAlphanumeric(16) + referer;
10 // 放到集合里
11 STATES.add(state);
12 // 构造 请求url 请求hacpai,回调/login/callback
13 final String loginAuthURL = "https://hacpai.com/login?goto=" + Latkes.getServePath() + "/login/callback";
14 // 加入state
15 final String path = loginAuthURL + "?state=" + URLs.encode(state);
16 // 重定向
17 context.sendRedirect(path);
18 }
猜一下
1.输入用户名密码
2.查询用户信息
3.截取 goto 路径
4.重定向 http://站点?state=state&userId=userId&userName=userName
1 @RequestProcessing(value = "/login/callback", method = HttpMethod.GET)
2 // `synchronized` 或许是为了极端情况下1000000人跑这个东西然后你拿着我的东西登进去了?
3 public synchronized void authCallback(final RequestContext context) {
4 // 首先验证state是不是本站发出的
5 String state = context.param("state");
6 if (!STATES.contains(state)) {
7 context.sendError(400);
8
9 return;
10 }
11 // 是的话就删了,免得被人用了
12 STATES.remove(state);
13 String referer = URLs.decode(state);
14 // 从第16位截取出站点地址
15 referer = StringUtils.substring(referer, 16);
16
17 final Response response = context.getResponse();
18 final Request request = context.getRequest();
19 // 拿到用户ID,名称,头像,我头像贼帅
20 final String openId = context.param("userId");
21 final String userName = context.param(User.USER_NAME);
22 final String userAvatar = context.param("avatar");
23 // 看看是不是有这个用户啊
24 JSONObject user = userQueryService.getUserByGitHubId(openId);
25 // 如果没有
26 if (null == user) {
27 // 是不是没初始化博客呢还,没初始化就初始化
28 if (!initService.isInited()) {
29 final JSONObject initReq = new JSONObject();
30 initReq.put(User.USER_NAME, userName);
31 initReq.put(UserExt.USER_AVATAR, userAvatar);
32 initReq.put(UserExt.USER_B3_KEY, openId);
33 initReq.put(UserExt.USER_GITHUB_ID, openId);
34 initService.init(initReq);
35 } else {
36 user = userQueryService.getUserByName(userName);
37 if (null == user) {
38 final JSONObject addUserReq = new JSONObject();
39 addUserReq.put(User.USER_NAME, userName);
40 addUserReq.put(UserExt.USER_AVATAR, userAvatar);
41 addUserReq.put(User.USER_ROLE, Role.VISITOR_ROLE);
42 addUserReq.put(UserExt.USER_GITHUB_ID, openId);
43 addUserReq.put(UserExt.USER_B3_KEY, openId);
44 try {
45 // 这我估计是加到用户列表里去了,没往下看了
46 userMgmtService.addUser(addUserReq);
47 } catch (final Exception e) {
48 LOGGER.log(Level.ERROR, "Registers via oauth failed", e);
49 context.sendError(500);
50
51 return;
52 }
53 } else {
54 user.put(UserExt.USER_GITHUB_ID, openId);
55 user.put(User.USER_NAME, userName);
56 user.put(UserExt.USER_AVATAR, userAvatar);
57 try {
58 userMgmtService.updateUser(user);
59 } catch (final Exception e) {
60 LOGGER.log(Level.ERROR, "Updates user GitHub id failed", e);
61 context.sendError(500);
62
63 return;
64 }
65 }
66 }
67 } else {
68 user.put(User.USER_NAME, userName);
69 user.put(UserExt.USER_AVATAR, userAvatar);
70 try {
71 userMgmtService.updateUser(user);
72 } catch (final Exception e) {
73 LOGGER.log(Level.ERROR, "Updates user name failed", e);
74 context.sendError(500);
75
76 return;
77 }
78 }
79
80 user = userQueryService.getUserByName(userName);
81 if (null == user) {
82 LOGGER.log(Level.WARN, "Can't get user by name [" + userName + "]");
83 context.sendError(404);
84
85 return;
86 }
87// 如果通过了校验,那就登录
88 Solos.login(user, response);
89 context.sendRedirect(referer);
90 LOGGER.log(Level.INFO, "Logged in [name={0}, remoteAddr={1}] with oauth", userName, Requests.getRemoteAddr(request));
91 }
4.造 Cookie
1public static void login(final JSONObject user, final Response response) {
2 try {
3 // 获取用户ID,如果没有就用Kes.OBJECT_ID:oId
4 final String userId = user.optString(Keys.OBJECT_ID);
5 final JSONObject cookieJSONObject = new JSONObject();
6 // map放userId进oid建
7 cookieJSONObject.put(Keys.OBJECT_ID, userId);
8 final String b3Key = user.optString(UserExt.USER_B3_KEY);
9 // 生成一个8位的带数字和字母的随机字符串
10 final String random = RandomStringUtils.randomAlphanumeric(8);
11 // emmm,Token b3key+随机字符串,存入MAP(原先是有密码混入的呦)
12 cookieJSONObject.put(Keys.TOKEN, b3Key + ":" + random);
13 // AES 加密 JSON的toString,key为lake配置文件中的cookieSecret,如果没有配置,那就是8位随机数字+字母字符串
14 final String cookieValue = Crypts.encryptByAES(cookieJSONObject.toString(), COOKIE_SECRET);
15// cookie: io.netty.handler.codec.http.cookie.Cookie cookie;
16// CookieNAME:lake配置中的cookieName如果没有那就是随机的
17//cookieValue是刚才那个MapToSring混入COOKIE_SECRET然后AES加密后的
18 final Cookie cookie = new Cookie(COOKIE_NAME, cookieValue);
19 // Cookie时间限制
20 cookie.setMaxAge(COOKIE_EXPIRY);
21 // Cookie路径
22 cookie.setPath("/");
23 // 我不知道这是啥
24 cookie.setHttpOnly(true);
25 // 放入Response中
26 response.addCookie(cookie);
27 } catch (final Exception e) {
28 LOGGER.log(Level.WARN, "Can not write cookie", e);
29 }
30 }
5.然后重定向到主页