YMLiang

单点登录(SSO => Single Sign On)

单点登录SSO是指Single Sign On 从一个系统登录,其他系统免登录,在一个系统用户增多,架构完善之后为了方便运营人员登录多个系统而不需要每次都输入用户名密码,所以实现单点登录显得尤为重要,这里分享一下我在项目中如何用单点登录实现用户登录一次即可访问其他相互信任的系统

  1. 首先我们的认证系统是独立的一个模块,即我们在用户登录后,会调用认证系统的方法来生成用户唯一的session并进行保存,认证系统返回给客户端一个唯一的登录凭证,用这个登录凭证即可直接访问其他的子系统不用再进行登录了
  1. 在进行登录认证返回登录凭证后,我们还需要配置一个拦截器,用于拦截服务的请求,即我们需要哪些请求要验证这个登录凭证才能访问我们的其他服务,这样写可能不是很清楚,举个栗子

    • 用户A登录网站,以post请求访问/xxx/login,再登录的同时去注册验证系统,返回一个登录状态(成功登录or失败)并附带一个登录验证后的凭证,这个凭证代表A可以访问其他的子服务
    • 当用户A访问B服务时拦截器起作用,拦截器控制如果想访问B服务,需要验证这个凭证是否生效,如果生效则放行,这就是单点登录如何通过配置拦截器控制访问的实现流程

      public class CheckInterceptor implements HandlerInterceptor {
      
          //发请求 restTemplate
          //专门调rest服务的对象
          @Autowired
          private RestTemplate restTemplate;
      
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                  throws Exception {
      
              //截取请求中的userId,ticket
              //ticket为凭证,这里凭证已经通过登录系统保存至浏览器,我们直接取即可
              String userId = request.getParameter("userId");
              String ticket = request.getParameter("ticket");
              // 将userId,ticket发给/user/ticket检测
              //返回结果是ReturnResult对象
              if(userId!=null&&ticket!=null){
                  //这里是拦截器需要访问这个请求,并设置参数进行验证
                  String url = "http://localhost:7001/user/ticket";
                  MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
                  params.set("userId", userId);
                  params.set("ticket", ticket);
                  ReturnResult result = restTemplate.postForObject(url, params, ReturnResult.class);
                  //返回结果的判断
                  if(result.getStatus()==yixueConstant.SUCCESS){
                      //校验正确,放行
                      return true;
                  }
              }
              //校验失败,拦截请求,给用户返回一个json结果
              response.setContentType("text/html;Charset=UTF-8");
              PrintWriter out = response.getWriter();
              out.print("{\"status\":-2,\"msg\":\"令牌凭证无效\"}");
              out.flush();
              return false;
          }
      }
      
    • 有了拦截器,我们还要把拦截器加入配置,使其生效

      @Component
      public class CheckInterceptorConfiguration implements WebMvcConfigurer {
          @Autowired
          private CheckInterceptor checkInterceptor;
      
          public void addInterceptors(InterceptorRegistry registry) {
              //添加要拦截的请求地址url,在我们访问视频模块时,需要先拦截请求,在拦截器中验证,如果返回结果为true则放行
              String[] urls = {"/course/chapter"};
              registry.addInterceptor(checkInterceptor).addPathPatterns(urls);
          }
      }
      

具体的完整流程(凭证的生成及存储)请参考我的另外一篇文章

这里我分享另外一篇技术博客给大家方便大家理解单点登录

 评论


博客内容遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议

本站使用 Material X 作为主题 , 总访问量为 次 。
Copyright 2018-2019 YMLiang'BLOG   |   京ICP备 - 19039949  |  载入天数...载入时分秒...