浅显易懂了解token单点登入原理及实现过程

什么是单点登入(SSO)

首先举个例子:
对于某个银行系统,本身有开发自己的系统,比如门户之类的。最近有新的新的需求,比如数据分析的业务需求,于是购买了一套数据分析系统、,之后又上线了一套贷款系统等等,如下图。那么用户在在登入操作的时候,就会面临一个问题,多个系统之间是不是需要登入多次呢?
在这里插入图片描述
比如我从门户页面进入系统,接下来要在贷款系统上进行操作,那是不是又要输入一次用户名、密码?如果没有密码的话肯定会有安全问题。这时候就要用到SSO单点了,只需要在门户首页登入一次,在各个系统中可以进行免登入操作。

单点登录(Single Sign On),简称为 SSO,在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

常见的SSO有token回调、Oauth、cas,同时还可以集成在第三方系统上,比如微信、钉钉等。这篇文章主要介绍token单点登入。

token单点原理

在这里插入图片描述
a、首先要求用户登入自己的系统(银行系统),然后打开第三方系统,比如通过url访问第三方系统,在访问的时候携带上token(一般是作为参数直接拼接在url上);
b、当第三方系统接收到一个未登入的请求时,会调用客户系统(银行系统或者独立的验证系统)提供接口对这个token进行校验,如果检验成功,则返回用户信息(比如用户id,登入name),验证失败则跳转到错误页面;
c、第三方系统(数据分析系统)拿到这些信息后,对该请求根据返回的用户名进行登入处理。

对于自己的系统来说,需要完成的工作是:提供一个验证token的接口,在跳转到第三方系统时生成token并且放到请求中。对于第三方系统来说,需要开发一个拦截请求然后判断登入的逻辑(常见的处理方式是 过滤器)。

安全性

1、在整个过程中是没有用户名和密码的传递的,不会存在密码被盗用的风险;
2、对于自己的系统来说,不会让第三方公司知道自己的加密策略的加密手段,因为生成token和验证token的过程都是在自己系统上进行,第三方系统并不关心这个过程是如何进行的,只需要返回一个验证结果就行了;
3、比较担心的是token如果被拦截获取,是不是就可以从别的地方根据这个token登入第三方系统了呢?
分情况讨论吧:
a、首先一般这个token是一串很长的字符串,凭肉眼记忆几乎是不可能的,被盗的情况应该是这台电脑中病毒,从而请求被拦截并获取盗这些参数。对于内网环境、或者安全级别比较高的办公环境来说,这种可能性很小;
b、token往往具有时效性、一般有效期在2~3分钟(每个厂子的安全策略不同,控制的时间也不同),即使被拷贝给其他人,很快也会失效;
c、更高级的做法,就是token只能检验一次,然后就会被回收,这样几乎不存在泄露的问题。

token生成机制有很多,比如 通过MD5来进行加密得到加密串,md5(用户名 + 时间戳 + key)、或者hash算法生成等等。

代码演示

客户的回调接口java代码举例
public class TokenCheckServlet extends HttpServlet {

 private static final long serialVersionUID = 1L;

    
   public TokenCheckServlet() {

       super();

   }

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         String token = request.getParameter("token");
         if(token == null || "".equals(token.trim())) {
                //token不存在处理逻辑
         return;
         }
         else {
                 // 校验token是否合法
                 StringBuilder result = new StringBuilder();
                 
                 if(check(token)) {
                 //token验证通过就返回当前登录用户
                  result.append("{\"result\":\"success\",\"userId\":\"test\"}");
                 }
                 else {
                   // token验证没通过就不返回userId。
                   result.append("{\"error\":\"james\"}");
                 }

                 response.getWriter().write(result.toString());
         }
 }

 
/**
*校验tokan是否有效
*/
 private boolean check(String token) {
        return true;
 }
 
 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      doGet(request, response);
 }
}

猜你喜欢

转载自blog.csdn.net/samur2/article/details/106225829