SSO 简单介绍
Single Sign On 在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统。
单点登录的问题
- cookie不能跨域
解决:sso登录以后,可以将Cookie的域设置为顶域,即.a.com,这样所有子域的系统都可以访问到顶域的Cookie。我们在设置Cookie时,只能设置顶域和自己的域,不能设置其他的域。
- session不能共享
解决:共享session,如springSession,或者使用认证中心,使用认证中心的作用就是,用户只要在认证中心登陆了,就等同于登陆了所有系统.
这样用户访问其他系统的时候就应该首先去访问认证中心是否已经登陆了该用户.假如没有登陆就应该由认证中心引导用户登陆并将登陆成功的信息返回给原系统.
认证中心内应该还需存有能够在中心注册的认证的所有子系统的地址信息.
这里我有一点很不解,认证中心如何确定用户身份信息?及它怎么知道其他系统的登陆的是哪个用户?
其实感觉还是要回到cookie内.希望后面可以弄明白
初次实现简易认证中心
@RestController
public class AuthController {
public static HashMap<String, String> tokens = new HashMap<>();
@Autowired
RestTemplate restTemplate; @GetMapping(value = "/isLogin/{token}")
public Result isLogin(@PathVariable("token") String token, HttpServletRequest request) {
//查询本地认证中心本地session或者redis或者 该用户是否已经登陆
//todo
//模拟已登陆
//代表已登陆,生成一个唯一token 传给客户端.并在本地存储相应的键值
//在tokens里根据这个token来查找是否存在,//todo JWT了解一下
//存在就把这个令牌回显,然后将令牌回显,该用户已经在认证中心登陆
Result result = new Result();
if (tokens.containsKey(token)) {
//todo 这里可以加深加密的逻辑,不应该这么简单
result.setMsg("用户已经登陆");
return result;
} else {
//未登录 跳转到登陆页面
Result result1 = new Result();
result1.setMsg("用户未登陆,请引导登陆!");
return result1;
}
}
@PostMapping(value = "/login")
public Result login(User user) {
//验证登陆
if ("123".equals(user.getPassword())) {
//登陆成功还是要在认证中心存储该用户
String tkV = UUID.randomUUID().toString();
String tkK = UUID.randomUUID().toString();
//key值不应该为username,这里为了简便.
//todo 存储到数据库或者redis都可以
tokens.put(tkK, tkV);
//然后返回给app 一个唯一token 并将该token也存入redis 或者数据库 这里失去了 原应用的uri
Result result = new Result();
result.setMsg("登陆成功");
//将key值返回给app
result.setToken(tkK);
return result;
} else {
//登陆失败,重新登陆
return null;
}
}
}
来自在校学生的挣扎.