IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 单点登录总结(共享cookie、传统SSO、JWT、Gateway) -> 正文阅读

[Java知识库]单点登录总结(共享cookie、传统SSO、JWT、Gateway)

1.共享cookie实现单点登录

1.1 单系统登录的解决方案是cookie,cookie携带会话id在浏览器与服务器之间维护会话状态。但是cookie是有限制的,这个限制就是cookie的域(通常对应网站的域名),浏览器发送http请求时会自动携带与该域匹配的cookie,而不是所有cookie。

1.2 共享cookie的方式存在众多局限:
1)首先,应用群域名得统一;
2)应用群各系统使用的技术(至少是web服务器)要相同,不然cookie的key变量(tomcat为JSESSIONID)不同,无法维持会话,共享cookie的方式是无法实现跨语言技术平台登录的,比如java、php、.net系统之间;
cookie本身不安全。

2.单点登录SSO

2.1 什么是单点登录:

单点登录全称Single Sign On(以下简称SSO),是指在多系统应用群中登录一个系统,便可在其他所有系统中得到授权而无需再次登录,包括单点登录与单点注销两部分

2.2 sso登录流程:

sso需要一个独立的认证中心,只有认证中心能接受用户的用户名密码等安全信息。sso认证中心验证用户的用户名密码没问题,创建授权令牌,在接下来的跳转过程中,授权令牌作为参数发送给各个子系统,子系统拿到令牌,即得到了授权,可以借此创建局部会话,局部会话登录方式与单系统的登录方式相同

2.3 sso注销流程
单点登录自然也要单点注销,在一个子系统中注销,所有子系统的会话都将被销毁

用户向系统1发起注销请求
系统1根据用户与系统1建立的会话id拿到令牌,向sso认证中心发起注销请求
sso认证中心校验令牌有效,销毁全局会话,同时取出所有用此令牌注册的系统地址
sso认证中心向所有注册系统发起注销请求
各注册系统接收sso认证中心的注销请求,销毁局部会话
sso认证中心引导用户至登录页面

3.JWT单点登录

以上的session还有token的方案,在集群环境下,都是靠第三方缓存数据库redis来实现数据的共享。
跟以上那些唯一的不同点就是:token存放了用户的基本信息,更直观一点就是将原本放入redis中的用户数据,放入到token中去了!

JWT相比session方案,因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA、JavaScript、PHP等很多语言都可以使用,而session方案只针对JAVA。

因为有了payload部分,所以JWT可以存储一些其他业务逻辑所必要的非敏感信息。

4.Gateway

1.使用Route结合Hystrix实现默认降级策略
2.使用GatewayFilter接口,自定义过滤器类,实现登录态(token)校验

前端请求时path带/gateway/,在gateway层使用StripPrefix=1,去掉gateway,最终微服务上的path不带"/gateway/".
使用Hystrix实现默认降级策略,降级接口实现如下:

    @Slf4j
    @RestController
    public class DefaultHystrixController {
     
        @RequestMapping("/defaultfallback")
        public ApiResult defaultfallback(){
     
            log.info("服务降级中");
            return ApiResult.failure("服务异常");
        }
    }

4.1 实现登录态(token)校验-自定义过滤器,实现GatewayFilter, Ordered 2个接口。

import com.*.auth.UserTokenTools;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
 
/**
 * @Description token过滤器
 */
@Slf4j
@Component
public class LoginTokenFilter implements GatewayFilter, Ordered {
 
    private static final String AUTHORIZE_TOKEN = "Authorization";
    private static final String BEARER = "Bearer ";
 
    /**
     * token过滤
     *
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("当前环境已开启token校验");
        ServerHttpRequest request = exchange.getRequest();
        HttpHeaders headers = request.getHeaders();
        ServerHttpResponse response = exchange.getResponse();
        // 取Authorization
        String tokenHeader = headers.getFirst(AUTHORIZE_TOKEN);
        log.info("tokenHeader=" + tokenHeader);
        // token不存在
        if (StringUtils.isEmpty(tokenHeader)) {
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        // 取token
        String token = this.getToken(tokenHeader);
        log.info("token=" + token);
 
        // token不存在
        if (StringUtils.isEmpty(token)) {
            log.info("token不存在");
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        // 校验 token是否失效
        if (UserTokenTools.isTokenExpired(token, null)) {
            log.info("token失效");
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        // 校验 token是否正确
        if (!UserTokenTools.checkToken(token, null)) {
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
 
//        //有token 这里可根据具体情况,看是否需要在gateway直接把解析出来的用户信息塞进请求中,我们最终没有使用
//        UserTokenInfo userTokenInfo = UserTokenTools.getUserTokenInfo(token);
//        log.info("token={},userTokenInfo={}",token,userTokenInfo);
//        request.getQueryParams().add("token",token);
        //request.getHeaders().set("token", token);
        return chain.filter(exchange);
    }
 
 
    @Override
    public int getOrder() {
        return -10;
    }
 
    /**
     * 解析Token
     */
    public String getToken(String requestHeader) {
        //2.Cookie中没有从header中获取
        if (requestHeader != null && requestHeader.startsWith(BEARER)) {
            return requestHeader.substring(7);
        }
        return "";
    }
}

4.2配置路由,可根据具体情况,如果只有一套登录态,那就用一个filter即可。

import com.*.gateway.filter.AuthorizeGatewayFilter;
import com.*.gateway.filter.LoginTokenFilter;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
 
@Configuration
public class GatewayConfig {
 
    @Bean
    public RouteLocator getRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                // token校验1
                .route(predicateSpec -> predicateSpec
                        .path("/gateway/pay/card/**", "/gateway/app/**")
                        .filters(gatewayFilterSpec -> gatewayFilterSpec.stripPrefix(1).filter(new AuthorizeGatewayFilter()))
                        .uri("lb://OLOAN-PAY-SERVICE")
                        .id("OLOAN-PAY-SERVICE-token"))
 
                // token校验2
                .route(predicateSpec -> predicateSpec
                        .path("/gateway/order-audit/**", "/gateway/order/**", "/gateway/order-payment/**")
                        .filters(gatewayFilterSpec -> gatewayFilterSpec.stripPrefix(1).filter(new LoginTokenFilter()))
                        .uri("lb://OLOAN-ORDER-SERVICE")
                        .id("OLOAN-ORDER-ORDER-token"))
                .build();
    }
}

yml参考

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: false
          #开启小写验证,默认feign根据服务名查找都是用的全大写
          lowerCaseServiceId: true
      default-filters:
        - AddResponseHeader=X-Response-Default-Foo, Default-Bar
      routes:
        - id: OLOAN-FINANCIAL-PRODUCT-SERVICE
          # lb代表从注册中心获取服务
          uri: lb://OLOAN-FINANCIAL-PRODUCT-SERVICE
          predicates:
            # 转发该路径
            - Path=/gateway/financialProduct/**
          # 带前缀
          filters:
            - StripPrefix=1
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/defaultfallback
        - id: ADMIN-SERVICE
          uri: lb://ADMIN-SERVICE
          predicates:
            - Path=/gateway/auth/**
          filters:
            - StripPrefix=2
            - name: Hystrix
              args:
                name: fallbackcmd
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-10 11:43:27  更:2022-05-10 11:45:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:10:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码