sso单点登录

Nginx

  1. nginx 服务器: 192.168.75.128:81

  2. tomact1: 192.168.75.128:9090

  3. tomcat2:192.168.75.128:9091

SSO单点登录

redis c语言 key-value

  • 字符: json

  • 散列:Map

  • 列表:list

  • 集合:Set

  • 有序集合:HashSet

    应用场景

    1. 缓存
    2. 分布式集群架构的session分离 (http无状态 cookie 有状态 session服务端 判断用户是谁)
    3. 好友列表
    4. 消息队列 不用 我们用专门的
    5. 排行榜
    6. 网站访问量
    7. 数据
    8. 数字自增 日期 毫秒 并发 yyymmddhhmmss+redis的自增数字 订单号的生成方案

    Redis高可用解决方案

    • keepalived

    • zookeeper

    • sentinel

      主要解决单点故障

    • 应用 -> sso单点登录

    传统登录机制

    1. session会话机制 通过 将token 存到客户端的cookie ,之后每次客户端请求时携带token值让客户端识别WhoAmI

      缺陷
      1. 同源机制:必须在同源下才可以共享token
      2. 当创建多个不同服务器时(php/java/.net/) 所提供的session机制不同,会导致不识别
      3. cookie不安全

    SSO单点登录 解决上诉痛点

    • 步骤:
    1. 查询用户信息 redis到mysql service层

      • 获取cookie中的token的value,作为key查询Redis是否有value(用户名):有(已经登陆过) 提供user。 无 继续

      • 去数据库查询有无该用户信息 ,有,将username,password存到redis(第一次登陆),无,返回null(未登录)

    2. sso登录服务 controller层

      • 返回非null(且第一次登陆) 登录成功 用CookieUtil生成一个随机num,<num,userId>存放到Redis中(熔断了返回刷新重试), <token,num>存放到客户端, -> 登录成功
      • 返回null -> 登录失败/未登录
    • 效果:通过redis实现统一的session管理,解决缺陷2,无论何种服务器,存储数据格式方案一致,token从客户端到服务端两次分离,解决cookie不安全(缺陷3);同源机制可以通过nginx反向代理解决/Zuul网关。

    • th拦截器可以用vue判断json返回 是否执行跳转。

    • 拦截器还有个拦截Config 拦截所有资源,去到下列拦截执行器中

      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
      31
      32
      33
      package com.admin.interceptor;
      public class WebAdminInterceptor implements HandlerInterceptor{

      @Overrider
      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
      //cookie 为空 一定没有登陆 ->去单点登录
      String token = CookieU ~~
      response.senRedirect("http://login.html"); // 该常量可以放进config里面
      return false;

      }
      @Overrider
      public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modeAndView){
      //cookie有,但是不一定登录 session里那数据
      HttpSession session = request.getSession();
      User user = session.getAttribute("user"); //局部会话
      //user不为空 处于局部会话的已登录状态----------------------------
      modelAndView.addObject("user",user); //提供给下一个跳转的有缘人

      //user为空 处于未登录状态--------------------------------------
      //Cookie 拿到的token ,value作为key去Redis查询 ,拿到loginCode 去mapper拿到完整user
      //如果loginCode不为空 -> 已登录 创建局部会话,并把user存放到里面
      request.getSession().setAttribute("user",user);

      //二次确认
      user == null ;
      //直接重定向到登录系统
      }
      @Overrider
      public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Execption ex){

      }
      }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//出现问题
//RedisService无法被自动注入
class InterceptorConfig implements WebMvcConfigurer{
@Bean
WebAdminInterceptor webAdminInterceptor(){
return new WebAdminInterceptor();
}
@Override
public void addIntercepotrs(InterceptorRegistry registry){
registry.addIntercptor(new WebAdminInterceptor())
.addPathPatterns("/**")
.excluedPathPatterns("/static");
}
}
  • 跨域:同源策略下的脚本安全问题,浏览器限制脚本只能在同源下执行,但是现在是微服务,可能位于不同ip/域名/端口,导致存在。

    解决:

    1. CORS跨资源共享,浏览器自动完成,在header设置即可,关键在服务器实现CORS接口即可:-1:不支持老式浏览器
    2. Jsonp 利用<script>的开放策略 ,前端从json解析器变成JavaScript直译器,需要目标服务器配合calback函数。:+1:支持老式浏览器,:-1:只支持get请求,需要客户端服务端同时改变
    3. Nginx反向代理:挺好的

    方案3步骤:在docker-compose.yml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    user nginx:
    ~~~~~
    server{
    listen 80;
    server_name 192.168.75.128;
    location /{
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Headers X-Requested-With;
    add_header Access-Control-Methods GET,POST,OPTIONS;

    数据卷
    }
    }
0%