>  기사  >  백엔드 개발  >  Single Sign-On 원칙 및 간단한 구현

Single Sign-On 원칙 및 간단한 구현

PHPz
PHPz원래의
2017-03-12 16:28:153791검색

1. 단일 시스템 로그인 메커니즘

1. http없음상태프로토콜

애플리케이션사용 서버아키텍처, http를 통신 프로토콜로 사용합니다. http는 상태 비저장 프로토콜입니다. 브라우저의 모든 요청은 서비스 서버에 의해 독립적으로 처리되며 이전 또는 후속 요청과 연결되지 않습니다. 이 프로세스는 아래 그림에 설명되어 있습니다. 세 가지 요청/응답 쌍. 모든 연락처

Single Sign-On 원칙 및 간단한 구현

그러나 이는 또한 모든 사용자가 브라우저를 통해 서버 리소스에 액세스할 수 있음을 의미합니다. 브라우저 요청을 제한해야 하며, 브라우저 요청을 식별하고, 합법적인 요청에 응답하고, 불법적인 요청을 무시하여 브라우저 요청 상태를 알아야 합니다. http 프로토콜은 상태 비저장이므로 서버와 브라우저가 함께 상태를 유지하도록 하세요! 이것이 세션 메커니즘입니다

2. 세션 메커니즘

브라우저가 서버에 처음 요청하면 서버는 세션을 생성하고 응답의 일부로 세션 ID를 브라우저에 보냅니다. 브라우저는 세션 ID를 저장하고 두 번째 및 세 번째 후속 요청에서 세션 ID를 가져옵니다. 서버는 요청에서 세션 ID를 가져와 동일한 사용자인지 여부를 알 수 있습니다. 첫 번째 요청과 동일합니다.

Single Sign-On 원칙 및 간단한 구현

서버는 세션 객체 를 메모리에 저장합니다. ? 두 가지 방법을 생각할 수 있습니다

  1. 요청 매개변수

  2. 쿠키

세션 ID를 각 요청의 매개변수로 사용하면 서버는 요청을 받을 때 자연스럽게 매개변수를 구문 분석하여 세션 ID를 얻을 수 있으며, 이를 사용하여 동일한 세션에서 오는지 여부를 확인할 수 있습니다. 이 방법은 신뢰할 수 없습니다. 그런 다음 브라우저가 세션 ID를 자체적으로 유지하도록 하십시오. 쿠키 메커니즘을 사용하여 이를 수행할 때마다 브라우저가 자동으로 세션 ID를 보냅니다. 쿠키는 브라우저가 소량의 데이터를 저장하기 위해 사용하는 메커니즘입니다. 데이터는 "/값" 형식으로 저장되며, 브라우저는 http 요청을 보낼 때 자동으로 쿠키 정보를 첨부합니다.

물론 Tomcat 세션 메커니즘도 쿠키가 구현되어 있습니다. Tomcat 서버에 액세스하면 브라우저에서 "JSESSIONID"라는 쿠키를 볼 수 있습니다. Tomcat 세션 메커니즘에 의해 유지 관리되는 쿠키를 사용한 요청 응답 프로세스는 다음과 같습니다. 그림

Single Sign-On 원칙 및 간단한 구현

3. 로그인 상태

세션 메커니즘에 따라 로그인 상태는 다음과 같습니다. 이해하기 쉽습니다. 서버를 요청할 때 처음으로 사용자를 입력해야 한다고 가정합니다. 서버는 사용자 이름과 비밀번호를 가져와서 데이터베이스와 비교합니다. 정확하다면 현재 이 세션을 보유하고 있는 사용자가 합법적인 사용자라는 의미입니다. 이 세션은 "인증됨" 또는 "로그인됨" 등으로 표시되어야 합니다. 상태는 세션의 상태이므로 당연히 저장되어야 합니다. Tomcat은 세션 객체에 로그인 상태를 다음과 같이 설정합니다.


HttpSession session = request.getSession();
session.setAttribute("isLogin", true);

사용자가 다시 방문하면 Tomcat이 세션에 로그인 상태를 설정합니다. 로그인 보기


HttpSession session = request.getSession();
session.getAttribute("isLogin");

의 상태 로그인 상태를 구현하는 브라우저 요청 서버 모델 은 다음 그림

Single Sign-On 원칙 및 간단한 구현

보호된 리소스가 요청될 때마다 세션 개체의 로그인 상태를 확인하며 isLogin=true인 세션에만 액세스할 수 있으며 이에 따라 로그인 메커니즘이 구현됩니다.

2. 다중 시스템의 복잡성

웹 시스템은 고대에는 단일 시스템에서 오늘날에는 여러 시스템으로 구성된 응용 그룹으로 발전해 왔습니다. 하나씩 로그인하고 하나씩 로그아웃해야 하나요? 아래 사진과 같습니다

Single Sign-On 원칙 및 간단한 구현

웹 시스템은 단일 시스템에서 여러 시스템으로 구성된 애플리케이션 그룹으로 발전해 왔으며, 그 복잡성은 사용자가 아닌 시스템 자체가 부담해야 합니다. 웹 시스템이 내부적으로 아무리 복잡하더라도 사용자에게는 통일된 전체입니다. 즉, 사용자가 웹 시스템의 전체 애플리케이션 그룹에 액세스하는 것은 단일 시스템에 액세스하는 것과 같습니다. 🎜>

Single Sign-On 원칙 및 간단한 구현

단일 시스템 로그인 솔루션은 완벽하지만 다중 시스템 애플리케이션 그룹에는 더 이상 적합하지 않습니다. 이유는 무엇입니까?

단일 시스템 로그인 솔루션의 핵심은 쿠키입니다. 쿠키는 브라우저와 서버 간의 세션 상태를 유지하기 위해 세션 ID를 전달합니다. 하지만 쿠키에는 제한이 있습니다. 이 제한은 쿠키의 도메인(일반적으로 웹사이트의 도메인 이름에 해당)입니다. 브라우저가 http 요청을 보내면 모든 쿠키가 아닌 도메인과 일치하는 쿠키가 자동으로 전달됩니다. >

Single Sign-On 원칙 및 간단한 구현 이 경우 웹 애플리케이션 그룹에 있는 모든 하위 시스템의 도메인 이름을 "*.baidu.com"과 같은 하나의 최상위 도메인 이름으로 통합하는 것은 어떨까요? 그런 다음 쿠키 도메인을 "baidu.com"으로 설정하면 이 접근 방식은 이론적으로 가능하며 많은 초기 다중 시스템 로그인에서도 동일한 도메인 이름으로 쿠키를 공유하는 이 방법을 사용했습니다.

하지만 가능하다고 해서 좋은 것은 아니며, 쿠키를 공유하는 데에는 많은 제약이 따릅니다. 우선, 애플리케이션 그룹의 도메인 이름이 통일되어야 합니다. 둘째, 애플리케이션 그룹의 각 시스템(적어도 웹 서버)에서 사용하는 기술이 동일해야 합니다. 그렇지 않으면 쿠키의 키 값(Tomcat의 경우 JSESSIONID)이 동일해야 합니다. )이 다르면 세션을 유지할 수 없으며 쿠키 공유 방법을 국경을 넘어 구현할 수 없습니다. java, php, .net 시스템과 같은 언어 기술 플랫폼 로그인 셋째, 쿠키 자체는

안전하지 않습니다.

따라서 다중 시스템 응용그룹의 로그인을 구현하기 위해서는 새로운 로그인 방식이 필요하며, 바로 Single Sign-On

3. Single Sign-On

What 로그인하려면 클릭하세요? Single Sign-On의 전체 이름은 Single Sign On(이하 SSO)입니다. 다중 시스템 응용 프로그램 그룹에서 한 시스템에 로그인하면 다시 로그인하지 않고도 다른 모든 시스템에서 인증이 가능하다는 의미입니다. .싱글 사인온(Single Sign On)과 싱글 로그아웃(Single Logout)이 포함됩니다.

1. 로그인

단일 시스템 로그인에 비해 SSO는 독립적인 인증 센터만 사용자의 사용자 이름과 비밀번호를 허용합니다. 기타 보안 정보 기타 시스템에서는 로그인 진입을 제공하지 않습니다. 간접 인증은 토큰을 통해 구현됩니다. SSO 인증 센터는 사용자의 사용자 이름과 비밀번호가 올바른지 확인하고 인증 토큰을 생성합니다. 다음 점프 프로세스에서는 인증 토큰이 매개변수로 각 하위 시스템에 전송됩니다. token. 즉, 부분 세션을 생성할 수 있는 권한이 부여됩니다. 부분 세션 로그인 방법은 단일 시스템 로그인 방법과 동일합니다. Single Sign-On의 원리인 이 프로세스는 다음 그림으로 설명됩니다.

다음은 위 그림에 대한 간략한 설명입니다. 시스템 1. 시스템 1은 사용자가 로그인되어 있지 않음을 발견하고 SSO 인증 센터로 점프하여 자신의 주소를 매개 변수로 사용합니다

sso 인증 센터는 사용자가 로그인하지 않았으며 로그인 페이지로 이동합니다
  1. 사용자가 로그인 신청서를 제출하기 위해 사용자 이름과 비밀번호를 입력합니다
  2. SSO 인증센터에서는 사용자 정보 확인, 사용자 생성, SSO 인증을 진행합니다. 센터 간 세션을 글로벌 세션이라고 하며 동시에 인증 토큰이 생성됩니다
  3. Sso 인증 센터에서는 토큰을 가지고 초기 요청 주소(시스템 1)로 점프
  4. 시스템 1이 토큰을 받고 SSO 인증 센터로 가서 토큰이 유효한지 확인합니다
  5. SSO 인증 센터는 토큰을 확인하고 유효한 토큰을 반환한 후 시스템 1을 등록합니다.
  6. 시스템 1은 토큰을 사용하여 사용자와 세션을 생성합니다. 부분 세션, 보호된 리소스 반환
  7. 사용자가 System 2에 액세스 보호된 리소스
  8. System 2에서 사용자가 로그인되어 있지 않음을 발견합니다. sso 인증센터로 점프하여 자신의 주소를 인자로 사용
  9. sso 인증센터는 사용자가 로그인한 것을 확인하고 다시 시스템 2의 주소로 점프하여 접속한다. 토큰
  10. 시스템 2는 토큰을 받아 SSO 인증 센터로 가서 토큰이 유효한지 확인
  11. SSO 인증 센터에서 토큰, 유효 반환, 시스템 2 등록
  12. 시스템 2는 토큰을 사용하여 사용자와의 부분 세션 생성, 보호된 리소스 반환

  用户登录成功之后,会与sso认证中心及各个子系统建立会话,用户与sso认证中心建立的会话称为全局会话,用户与各个子系统建立的会话称为局部会话,局部会话建立之后,用户访问子系统受保护资源将不再通过sso认证中心,全局会话与局部会话有如下约束关系

  1. 局部会话存在,全局会话一定存在

  2. 全局会话存在,局部会话不一定存在

  3. 全局会话销毁,局部会话必须销毁

  你可以通过博客园、百度、csdn、淘宝等网站的登录过程加深对单点登录的理解,注意观察登录过程中的跳转url与参数

2、注销

  单点登录自然也要单点注销,在一个子系统中注销,所有子系统的会话都将被销毁,用下面的图来说明

Single Sign-On 원칙 및 간단한 구현

  sso认证中心一直监听全局会话的状态,一旦全局会话销毁,监听器将通知所有注册系统执行注销操作

  下面对上图简要说明

  1. 用户向系统1发起注销请求

  2. 系统1根据用户与系统1建立的会话id拿到令牌,向sso认证中心发起注销请求

  3. sso认证中心校验令牌有效,销毁全局会话,同时取出所有用此令牌注册的系统地址

  4. sso认证中心向所有注册系统发起注销请求

  5. 各注册系统接收sso认证中心的注销请求,销毁局部会话

  6. sso认证中心引导用户至登录页面

四、部署图

  单点登录涉及sso认证中心与众子系统,子系统与sso认证中心需要通信以交换令牌、校验令牌及发起注销请求,因而子系统必须集成sso的客户端,sso认证中心则是sso服务端,整个单点登录过程实质是sso客户端与服务端通信的过程,用下图描述

Single Sign-On 원칙 및 간단한 구현

  sso认证中心与sso客户端通信方式有多种,这里以简单好用的httpClient为例,web service、rpc、restful api都可以

五、实现

  只是简要介绍下基于java的实现过程,不提供完整源码,明白了原理,我相信你们可以自己实现。sso采用客户端/服务端架构,我们先看sso-client与sso-server要实现的功能(下面:sso认证中心=sso-server)

  sso-client

  1. 拦截子系统未登录用户请求,跳转至sso认证中心

  2. 接收并存储sso认证中心发送的令牌

  3. 与sso-server通信,校验令牌的有效性

  4. 建立局部会话

  5. 拦截用户注销请求,向sso认证中心发送注销请求

  6. 接收sso认证中心发出的注销请求,销毁局部会话

  sso-server

  1. 验证用户的登录信息

  2. 创建全局会话

  3. 创建授权令牌

  4. 与sso-client通信发送令牌

  5. 校验sso-client令牌有效性

  6. 系统注册

  7. 接收sso-client注销请求,注销所有会话

  接下来,我们按照原理来一步步实现sso吧!

1、sso-client拦截未登录请求

  java拦截请求的方式有servlet、filter、listener三种方式,我们采用filter。在sso-client中新建LoginFilter.java类并实现Filter接口,在doFilter()方法中加入对未登录用户的拦截


public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;
    HttpSession session = req.getSession();
    if (session.getAttribute("isLogin")) {
        chain.doFilter(request, response);
        return;
    }
    //跳转至sso认证中心
    res.sendRedirect("sso-server-url-with-system-url");
}

2、sso-server拦截未登录请求

  拦截从sso-client跳转至sso认证中心的未登录请求,跳转至登录页面,这个过程与sso-client完全一样

3、sso-server验证用户登录信息

  用户在登录页面输入用户名密码,请求登录,sso认证中心校验用户信息,校验成功,将会话状态标记为“已登录”


@RequestMapping("/login")
public String login(String username, String password, HttpServletRequest req) {
    this.checkLoginInfo(username, password);
    req.getSession().setAttribute("isLogin", true);
    return "success";
}

4、sso-server创建授权令牌

  授权令牌是一串随机字符,以什么样的方式生成都没有关系,只要不重复、不易伪造即可,下面是一个例子


String token = UUID.randomUUID().toString();

5、sso-client取得令牌并校验

  sso认证中心登录后,跳转回子系统并附上令牌,子系统(sso-client)取得令牌,然后去sso认证中心校验,在LoginFilter.java的doFilter()中添加几行


// 请求附带token参数
String token = req.getParameter("token");
if (token != null) {
    // 去sso认证中心校验token
    boolean verifyResult = this.verify("sso-server-verify-url", token);
    if (!verifyResult) {
        res.sendRedirect("sso-server-url");
        return;
    }
    chain.doFilter(request, response);
}

  verify()方法使用httpClient实现,这里仅简略介绍,httpClient详细使用方法请参考官方文档


HttpPost httpPost = new HttpPost("sso-server-verify-url-with-token");
HttpResponse httpResponse = httpClient.execute(httpPost);

6、sso-server接收并处理校验令牌请求

  用户在sso认证中心登录成功后,sso-server创建授权令牌并存储该令牌,所以,sso-server对令牌的校验就是去查找这个令牌是否存在以及是否过期,令牌校验成功后sso-server将发送校验请求的系统注册到sso认证中心(就是存储起来的意思)

  令牌与注册系统地址通常存储在key-value数据库(如redis)中,redis可以为key设置有效时间也就是令牌的有效期。redis运行在内存中,速度非常快,正好sso-server不需要持久化任何数据。

  令牌与注册系统地址可以用下图描述的结构存储在redis中,可能你会问,为什么要存储这些系统的地址?如果不存储,注销的时候就麻烦了,用户向sso认证中心提交注销请求,sso认证中心注销全局会话,但不知道哪些系统用此全局会话建立了自己的局部会话,也不知道要向哪些子系统发送注销请求注销局部会话

Single Sign-On 원칙 및 간단한 구현

7、sso-client校验令牌成功创建局部会话

  令牌校验成功后,sso-client将当前局部会话标记为“已登录”,修改LoginFilter.java,添加几行


if (verifyResult) {
    session.setAttribute("isLogin", true);
}

  sso-client还需将当前会话id与令牌绑定,表示这个会话的登录状态与令牌相关,此关系可以用java的hashmap保存,保存的数据用来处理sso认证中心发来的注销请求

8、注销过程

  用户向子系统发送带有“logout”参数的请求(注销请求),sso-client拦截器拦截该请求,向sso认证中心发起注销请求


String logout = req.getParameter("logout");
if (logout != null) {
    this.ssoServer.logout(token);
}

  sso认证中心也用同样的方式识别出sso-client的请求是注销请求(带有“logout”参数),sso认证中心注销全局会话


@RequestMapping("/logout")
public String logout(HttpServletRequest req) {
    HttpSession session = req.getSession();
    if (session != null) {
        session.invalidate();//触发LogoutListener
    }
    return "redirect:/";
}

  sso认证中心有一个全局会话的监听器,一旦全局会话注销,将通知所有注册系统注销


public class LogoutListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent event) {}
    @Override
    public void sessionDestroyed(HttpSessionEvent event) {
        //通过httpClient向所有注册系统发送注销请求
    }
}

위 내용은 Single Sign-On 원칙 및 간단한 구현의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.