Cookie实现SSO

介绍


两个拥有相同顶级域名的网站:
a: www.lb.xxxx (主网站)
b: game.lb.xxxx (需要共享登陆信息网站)
需要实现:登陆a网站,跳转b网站的时候,免登陆。同时保留b网站原有的登陆入口。
大致思路:

1,设置加密字段,存储用户主键、签名信息。
2,修改a网站登陆逻辑,增加登陆成功,回写加密字段到cookie。
3,修改b网站登陆逻辑,增加获取cookie自动登陆功能。

实现


设置加密字段

加密字段主要有3部分:

1,当前系统时间秒数,用于判断是否过期。
2,用户主键,用来获取用户信息。
3,签名信息,md5加密(当前时间+用户主键+密钥)生成签名信息,用于判断加密字段的合法性。

1
ticket = System.currentTimeMillis() / 1000 + userid + EncryptUtil.md5encode(System.currentTimeMillis() +userid+salt)
修改登陆逻辑

生成ticket字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private String _login(HttpServletRequest request, User user) {
SessionUtil.saveCurentUserId(request.getSession(), user.getId());

User o = new User();
o.setId(user.getId());
String tk = EncryptUtil.makeAuthTicket(user.getId());
o.setTicket(tk);
o.setLastoptat(new Date());
o.setLastoptip(HttpUtil.getClientAddr(request));
// 存取用户浏览器信息
o.setUserbrowser(BrowserUtil.getBrowserName(request
.getHeader("User-Agent")));
objectDao.updateByPrimaryKeySelective(o);
SessionUtil.saveCurentRoleId(request.getSession(), user.getRoleid());
SessionUtil.saveAuthTicket(request.getSession(), tk);
if (StringUtil.isNotBlank(user.getScope()))
SessionUtil.saveCurentShopId(request.getSession(),
Long.valueOf(user.getScope()));
else
SessionUtil.saveCurentShopId(request.getSession(), Long.valueOf(0));
return tk;
}

public static final String makeAuthTicket(long userId){
int expireAt = (int) Math.ceil(System.currentTimeMillis()/1000)+3600*4;
String sign = md5encode(""+expireAt+""+userId+secret);
return expireAt +"-" + userId +"-"+ sign;
}

回写ticket到cookie

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@ResponseBody
@RequestMapping({ "/userlogin" })
public Object userlogin(String mobile, String password,
HttpServletRequest request, HttpServletResponse resp)
throws Exception {
User user = null;

@SuppressWarnings({ "unused", "unchecked" })
Map<String, Object> map = this.userService.loginWithPwd(mobile,
password, request);

if (Integer.parseInt(map.get("code").toString()) == 1) {
user = (User) map.get("msg");

user.setPasswd(null);
loger.info("登陆成功获取TICKET:" + user.getTicket());

Cookie compCookie = new Cookie("ticket", user.getTicket());
compCookie.setMaxAge(60 * 60 * 24);
compCookie.setPath("/");
compCookie.setDomain("lb.world");//为了保证b网站可以获取cookie,必须设置成顶级域名。

resp.addCookie(compCookie);

return new ResultOk(user);

} else {
return new ResultFail(map.get("msg").toString());
}
}
修改b网站ticket登陆逻辑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@RequestMapping(value = { "/public/index", "/" })
public ModelAndView showIndex0(HttpServletResponse resp,
HttpSession session, HttpServletRequest request) throws IOException {
if (session.getAttribute("KEY_CURENT_USERID") == null) {
Cookie[] cookies = request.getCookies();
String ticket = "";
for (Cookie cookie : cookies) {
switch (cookie.getName()) {
case "ticket":
ticket = cookie.getValue();
break;
default:
break;
}
}

loger.debug("cookie 获取到ticket:" + ticket);
try {
userService.loginWithTicket(ticket, request);
} catch (Exception e) {
loger.error(e.getMessage());
}
}
loger.debug("免cookie 获取current_userid:"
+ session.getAttribute("KEY_CURENT_USERID"));

ModelAndView mv = new ModelAndView("redirect:/mh.html");
return mv;
}