资讯 小学 初中 高中 语言 会计职称 学历提升 法考 计算机考试 医护考试 建工考试 教育百科
栏目分类:
子分类:
返回
空麓网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
空麓网 > 计算机考试 > 软件开发 > 后端开发 > Java

从零开始搭建高负载java架构(05)——gateway网关节点(权限验证篇)

Java 更新时间: 发布时间: 计算机考试归档 最新发布

从零开始搭建高负载java架构(05)——gateway网关节点(权限验证篇)

目录

1. 基本原理

 2. 具体实现

2.1 通过mysql加载用户信息的实现

 2.2 实现基本的Security逻辑的配置类实现

2.3 实现基本的访问路径资源权限

2.4 登录验证中常用的回调函数自定义

 2.4.1 自定义登录成功回调ServerAuthenticationSuccessHandler

2.4.2 自定义登录失败回调ServerAuthenticationFailureHandler

2.4.3 自定义因未登录而访问未授权路径的回调ServerAuthenticationEntryPoint

 2.4.4 自定义访问未授权资源路径的回调ServerAccessDeniedHandler

2.4.5 自定义成功退出登录的回调ServerLogoutSuccessHandler

2.4.6 最终配置类引用上述自定义回调的修改


1. 基本原理

spring gateway采用的是webflux的反应式实现,因此对应的sring security也需要用webflux的处理方式,个人整理的WebFlux应用的认证过程如下:

  1. 用户通过form表单输入用户名和密码,通过POST请求登录认证
  2. 后台通过ServerFormLoginAuthenticationConverter类的convert接口,把获取到的用户名和密码封装成一个UsernamePasswordAuthenticationToken对象(Authentication的子类),然后把它传递给 ReactiveAuthenticationManager进行认证。
  3. ReactiveAuthenticationManager的认证逻辑接口authenticate
    (1) 如果认证失败则返回null,程序会自动跳到第1 步让用户重新输入用户名和密码
    (2) 如果认证成功则返回UsernamePasswordAuthenticationToken对象(authenticated字段被设置为true),并进行下面的步骤
  4. 将返回的UsernamePasswordAuthenticationToken对象通过类ServerSecurityContextRepository的save接口,把UsernamePasswordAuthenticationToken对象保存到SecurityContext对象中
  5. 然后默认会将用户重定向到之前访问的页面。
  6. 用户登录认证成功后再次访问之前受保护的资源时,就会调用ReactiveAuthorizationManager类的check接口对用户访问的路径进行权限鉴定,如不存在对应路径的访问权限,则默认会返回 403 错误码(如果要特殊处理,可以实现ServerAccessDeniedHandler类的handle接口,返回特定的信息)。

【注意】另外,如果要通过数据库或redis查找用户信息,可以重载实现ReactiveUserDetailsService的接口findByUsername,从其他数据源里查出user数据转成UserDetails对象,如果除了用户名和密码,还有其他额外的用户信息需要保存,可以重置UserDetails类,添加额外的信息

基本逻辑类都在包: spring-security-core-6.0.3.jar中

  1. AuthenticationWebFilter登录认证过滤器的filter接口
    包路径:org.springframework.security.web.server.authentication
  2. ServerFormLoginAuthenticationConverter 登录认证:
    包路径:org.springframework.security.web.server.authentication
    调用包:org.springframework.security.web.server的同名类:
    ServerFormLoginAuthenticationConverter的apply接口
    取Form转成Map的username和password
  3. ServerHttpBasicAuthenticationConverter类
    包路径:org.springframework.security.web.server.authentication
    http头字段:Authorization
    格式:Basic base64(用户名:密码)
  4. 默认的观察者模式ReactiveAuthenticationManager类:
    ObservationReactiveAuthenticationManager
    包路径:org.springframework.security.authentication
  5. 默认的ReactiveAuthenticationManager:
    UserDetailsRepositoryReactiveAuthenticationManager
    (主要验证逻辑在父类:AbstractUserDetailsReactiveAuthenticationManager)
    验证通过在createUsernamePasswordAuthenticationToken接口中设置登录验证通过标识authenticated为true
    包路径:org.springframework.security.authentication
  6. 默认的ServerSecurityContextRepository:
    WebSessionServerSecurityContextRepository
  7. 默认的SecurityContext:
    SecurityContextImpl
    包路径:org.springframework.security.core.context
  8. 默认的ReactiveAuthorizationManager:
    AuthenticatedReactiveAuthorizationManager
    包路径:org.springframework.security.authorization

 2. 具体实现

2.1 通过mysql加载用户信息的实现

基本的重载方法,为了支持从数据库查找用户登录信息,实现接口类:UserDetails

package com.cloudservice.gateway_service.security;import java.util.Collection;import java.util.Set;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.userdetails.UserDetails;public class GatewayUserDetails implements UserDetails {    private Long id;            // 用户id    private String password;    // 密码    private String username;    // 用户名    private boolean enabled;    // 帐户是否可用    private Set authorities;  // 权限信息    public Long getId() {        return id;    }    public void setId(Long id) {        this.id = id;    }    @Override    public Collection getAuthorities() {        return authorities;    }    public void setAuthorities(Set authorities) {        this.authorities = authorities;    }    @Override    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }    @Override    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    @Override    public boolean isAccountNonExpired() {        // TODO 帐号是到到期        return true;    }    @Override    public boolean isAccountNonLocked() {        // TODO 帐号是否锁定        return true;    }    @Override    public boolean isCredentialsNonExpired() {        // TODO 密码是否到期        return true;    }    @Override    public boolean isEnabled() {        return this.enabled;    }    public void setEnabled(boolean enabled) {        this.enabled = enabled;    }}

定义用户表的领域类:Users

package com.cloudservice.gateway_service.security;import java.util.HashSet;import java.util.Set;import jakarta.persistence.Entity;import jakarta.persistence.GeneratedValue;import jakarta.persistence.GenerationType;import jakarta.persistence.Id;import jakarta.validation.constraints.NotNull;import jakarta.validation.constraints.Size;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@Data@AllArgsConstructor@NoArgsConstructor@Entitypublic class Users {    @Id    @GeneratedValue(strategy = GenerationType.AUTO)    private Long id;    @NotNull    @Size(min=5, message="Username must be at least 5 characters long")    private String username;    @NotNull    private String password;    private boolean enabled;    public GatewayUserDetails to_user_details() {        GatewayUserDetails userDetails = new GatewayUserDetails();        userDetails.setId(id);        userDetails.setUsername(username);        userDetails.setPassword(password);        userDetails.setEnabled(enabled);        // 此处为了测试路径权限,写死order路径权限,实际中应该是从角色与路径的授权表groups_authorities里读取加载        Set authorities = new HashSet();        authorities.add(new GatewayUserGrantedAuthority("/order/"));        userDetails.setAuthorities(authorities);        return userDetails;    }    public static Users from_user_details(GatewayUserDetails userDetails) {        return new Users(userDetails.getId()                    , userDetails.getUsername()                    , userDetails.getPassword()                    , userDetails.isEnabled());    }}

简单通过使用JPA 的Repository类来根据用户名查数据库返回基本的用户信息:

package com.cloudservice.gateway_service.security;import org.springframework.data.repository.CrudRepository;public interface UsersRepository extends CrudRepository{    Iterable findByUsername(String username);}

 网关的nacos配置里加上mysql的datasource配置:

spring:
  datasource:
    url: jdbc:mysql://192.168.10.111:32001/gateway?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true
    username: mysql用户名
    password: mysql密码
    driver-class-name: com.mysql.cj.jdbc.Driver

 自定义加载用户信息的类ReactiveUserDetailsService:

package com.cloudservice.gateway_service.security;import java.util.ArrayList;import java.util.List;import org.apache.commons.codec.digest.DigestUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.core.userdetails.ReactiveUserDetailsService;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.stereotype.Component;import lombok.extern.slf4j.Slf4j;import reactor.core.publisher.Flux;import reactor.core.publisher.Mono;@Slf4j@Componentpublic class GatewayReactiveUserDetailsService implements ReactiveUserDetailsService {    @Autowired    private UsersRepository usersRepository;    @Override    public Mono findByUsername(String username) {        // TODO 优先查找缓存再查找数据库        // String Val1 = passwordEncoder.encode("123456");        log.info("gateway find user: {} {}", username, DigestUtils.sha256Hex("123456"));        List userDetailsList = new ArrayList();        usersRepository.findByUsername(username).forEach(user -> {            userDetailsList.add(user.to_user_details());        });        return Flux.fromIterable(userDetailsList).next();    }}

 2.2 实现基本的Security逻辑的配置类实现

package com.cloudservice.gateway_service.security;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;import org.springframework.security.config.web.server.ServerHttpSecurity;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.crypto.password.PasswordEncoder;import org.springframework.security.web.server.SecurityWebFilterChain;@Configuration@EnableWebFluxSecuritypublic class GatewaySecurityConfig {  @Bean  public PasswordEncoder passwordEncoder() {    return new BCryptPasswordEncoder();  }  @Bean  public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {    http      .authorizeExchange()        .pathMatchers("/favicon.*", "/login", "/logout").permitAll()        .anyExchange().authenticated()      .and().formLogin()      .and().csrf().disable();    return http.build();  }}

2.3 实现基本的访问路径资源权限

重载路径权限验证类 ReactiveAuthorizationManager,代码如下:

package com.cloudservice.gateway_service.security;import org.springframework.security.authentication.AuthenticationTrustResolver;import org.springframework.security.authentication.AuthenticationTrustResolverImpl;import org.springframework.security.authorization.AuthorizationDecision;import org.springframework.security.authorization.ReactiveAuthorizationManager;import org.springframework.security.core.Authentication;import org.springframework.security.web.server.authorization.AuthorizationContext;import org.springframework.stereotype.Component;import reactor.core.publisher.Mono;@Componentpublic class GatewayReactiveAuthorizationManager implements ReactiveAuthorizationManager{    private AuthenticationTrustResolver authTrustResolver = new AuthenticationTrustResolverImpl();    // 验证通过则返回:AuthorizationDecision(true)    // 验证失败则返回:AuthorizationDecision(false)    @Override    public Mono check(Mono authentication, AuthorizationContext context) {		return authentication                .filter(authentication_filter -> select_context(authentication_filter, context))                .map(authentication_map -> authenticate(authentication_map, context))				.defaultIfEmpty(new AuthorizationDecision(false));    }    private boolean select_context(Authentication authentication, AuthorizationContext context) {        // String req_path = context.getExchange().getRequest().getURI().getPath();        // log.info("check filter path: {}", req_path);		return !this.authTrustResolver.isAnonymous(authentication);	}    private AuthorizationDecision authenticate(Authentication authentication, AuthorizationContext context) {        if (authentication.isAuthenticated()) {            // 判断context.getExchange().getRequest().getPath()是否在authentication_notanonymous.getAuthorities()集合中            String req_path = context.getExchange().getRequest().getURI().getPath();            if (authentication.getAuthorities().contains(new GatewayUserGrantedAuthority(req_path)) == false) {                return new AuthorizationDecision(false);            }        }        return new AuthorizationDecision(authentication.isAuthenticated());    }}

用户可访问路径的集合存放在authorities集合里,为了支持集合类的contains操作,必须重载GrantedAuthority类并实现equals和hashCode接口,具体实现代码如下:

package com.cloudservice.gateway_service.security;import org.springframework.security.core.GrantedAuthority;public class GatewayUserGrantedAuthority implements GrantedAuthority, java.lang.Comparable {    String authority;    public GatewayUserGrantedAuthority() {}    public GatewayUserGrantedAuthority(String authority) {        this.authority = authority;    }    @Override    public String getAuthority() {        return this.authority;    }    public void setAuthority(String authority) {        this.authority = authority;    }    @Override    public int compareTo(Object obj) {        if (obj instanceof GatewayUserGrantedAuthority) {            return this.authority.compareTo(((GatewayUserGrantedAuthority)obj).getAuthority());        }        return 1;    }    public boolean equals(Object obj) {        if (!(obj instanceof GatewayUserGrantedAuthority)) {            return false;        }        if (obj == this) {            return true;        }        return this.authority.equals(((GatewayUserGrantedAuthority)obj).getAuthority());    }    public int hashCode() {        return this.authority.hashCode();    }} 

修改配置类GatewaySecurityConfig的springSecurityFilterChain接口,引用路径鉴权类GatewayReactiveAuthorizationManager:

@Configuration@EnableWebFluxSecuritypublic class GatewaySecurityConfig {  @Bean  public PasswordEncoder passwordEncoder() {    return new BCryptPasswordEncoder();  }  @Autowired  private GatewayReactiveAuthorizationManager gatewayReactiveAuthorizationManager;  @Bean  public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {    http      .authorizeExchange()        .pathMatchers("/favicon.ico", "/login", "/logout").permitAll()        .anyExchange().access(gatewayReactiveAuthorizationManager)      .and().formLogin()      .and().csrf().disable();    return http.build();  }}

2.4 登录验证中常用的回调函数自定义

 2.4.1 自定义登录成功回调ServerAuthenticationSuccessHandler

通过自定义登录成功时的回调函数,可以自定义登录成功后的返回消息,vue3中可以直接返回json格式,方便判断后在vue3的js代码中实现提示后跳转逻辑,实现代码如下:

package com.cloudservice.gateway_service.security;import org.springframework.core.io.buffer.DataBuffer;import org.springframework.http.server.reactive.ServerHttpResponse;import org.springframework.security.core.Authentication;import org.springframework.security.web.server.WebFilterExchange;import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler;import org.springframework.stereotype.Component;import org.springframework.web.server.ServerWebExchange;import com.fasterxml.jackson.databind.ObjectMapper;import lombok.extern.slf4j.Slf4j;import reactor.core.publisher.Mono;@Slf4j@Componentpublic class CustomLoginSuccessHandler implements ServerAuthenticationSuccessHandler{    @Override    public Mono onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) {        ServerWebExchange exchange = webFilterExchange.getExchange();        ServerHttpResponse response = exchange.getResponse();        response.getHeaders().add("Content-Type", "application/json; charset=UTF-8");        log.info("user login success: {}", authentication.getName());        Object principal = authentication.getPrincipal();        ObjectMapper  objectMapper = new ObjectMapper();        DataBuffer bodyDataBuffer = null;        try {            bodyDataBuffer = response.bufferFactory().wrap(objectMapper.writeValueAsBytes(principal));        } catch (Exception e) {            e.printStackTrace();        }        return response.writeWith(Mono.just(bodyDataBuffer));    }}

2.4.2 自定义登录失败回调ServerAuthenticationFailureHandler

通过自定义登录失败回调,可以定制返回登录失败的消息,vue3里一般需要返回json格式数据,实现代码如下:

package com.cloudservice.gateway_service.security;import java.util.HashMap;import org.springframework.core.io.buffer.DataBuffer;import org.springframework.http.HttpStatus;import org.springframework.http.server.reactive.ServerHttpResponse;import org.springframework.security.authentication.BadCredentialsException;import org.springframework.security.authentication.LockedException;import org.springframework.security.core.AuthenticationException;import org.springframework.security.web.server.WebFilterExchange;import org.springframework.security.web.server.authentication.ServerAuthenticationFailureHandler;import org.springframework.stereotype.Component;import com.alibaba.fastjson.JSON;import lombok.extern.slf4j.Slf4j;import reactor.core.publisher.Mono;@Slf4j@Componentpublic class CustomLoginFailureHandler implements ServerAuthenticationFailureHandler {    @Override    public Mono onAuthenticationFailure(WebFilterExchange webFilterExchange, AuthenticationException exception) {        ServerHttpResponse response = webFilterExchange.getExchange().getResponse();        response.setStatusCode(HttpStatus.FORBIDDEN);        response.getHeaders().add("Content-Type", "application/json; charset=UTF-8");        log.info("user login fail: {}", webFilterExchange.getExchange().getRequest().getPath());        HashMap map = new HashMap();        map.put("code", "-1001");        if (exception instanceof LockedException) {            map.put("message", "账户被锁定,请联系管理员!");        } else if (exception instanceof BadCredentialsException) {            map.put("message", "用户名或者密码输入错误,请重新输入!");        } else {            map.put("message", exception.getMessage());        }        DataBuffer dataBuffer = response.bufferFactory().wrap(JSON.toJSONBytes(map));        return response.writeWith(Mono.just(dataBuffer));    }}

2.4.3 自定义因未登录而访问未授权路径的回调ServerAuthenticationEntryPoint

通过自定义未登录而访问路径的错误回调 ,可以返回vue3需要的json格式,也可以强制跳转到登录页面,此处实现是强制跳转页面:

package com.cloudservice.gateway_service.security;import java.net.URI;import java.util.HashMap;import org.springframework.core.io.buffer.DataBuffer;import org.springframework.http.HttpStatus;import org.springframework.http.server.reactive.ServerHttpResponse;import org.springframework.security.core.AuthenticationException;import org.springframework.security.web.server.ServerAuthenticationEntryPoint;import org.springframework.stereotype.Component;import org.springframework.web.server.ServerWebExchange;import com.alibaba.fastjson.JSON;import lombok.extern.slf4j.Slf4j;import reactor.core.publisher.Mono;@Slf4j@Componentpublic class CustomNoLoginHandler implements ServerAuthenticationEntryPoint {    @Override    public Mono commence(ServerWebExchange exchange, AuthenticationException ex) {        return Mono.fromRunnable(() -> {            ServerHttpResponse response = exchange.getResponse();            response.setStatusCode(HttpStatus.FOUND);            response.getHeaders().add("Content-Type", "application/json; charset=UTF-8");            // 强制跳转到登录页面,在vue3中一般是返回json数据,并交由vue3来跳转            response.getHeaders().setLocation(URI.create("/login"));                log.info("url when no login: {}", exchange.getRequest().getPath());            HashMap map = new HashMap<>();            map.put("code", HttpStatus.FOUND.value());            map.put("message", "暂未登录,请您先进行登录");            DataBuffer dataBuffer = response.bufferFactory().wrap(JSON.toJSONBytes(map));            response.writeWith(Mono.just(dataBuffer));        });    }}

【注意】加了此自定义回调时,不能正常访问security默认定义的login页面,需要自定义登录页面,本人简单的实现示例:

此示例的controller使用到thymeleaf的模板,因此需要在pom.xml中引用依赖:


    org.springframework.boot
    spring-boot-starter-thymeleaf

创建一个用来接收GET方式的login请求的controller:

package com.cloudservice.gateway_service.security;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.GetMapping;@Controllerpublic class CustomLoginControl {    @GetMapping("/login")    public String login() {        return "login";    }}

 在src/main/resources/templates/目录下定义登录页面模板login.html

            Please sign in    

Please sign in

 2.4.4 自定义访问未授权资源路径的回调ServerAccessDeniedHandler

当访问资源路径进行权限验证时,ReactiveAuthorizationManager验证不通过,则会回调此类的接口,可以自定义返回的数据格式,代码如下:

package com.cloudservice.gateway_service.security;import java.util.HashMap;import org.springframework.core.io.buffer.DataBuffer;import org.springframework.http.HttpStatus;import org.springframework.http.server.reactive.ServerHttpResponse;import org.springframework.security.access.AccessDeniedException;import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler;import org.springframework.stereotype.Component;import org.springframework.web.server.ServerWebExchange;import com.alibaba.fastjson.JSON;import lombok.extern.slf4j.Slf4j;import reactor.core.publisher.Mono;@Slf4j@Componentpublic class CustomUrlNoRightHandler implements ServerAccessDeniedHandler{    @Override    public Mono handle(ServerWebExchange exchange, AccessDeniedException denied) {        ServerHttpResponse response = exchange.getResponse();        response.setStatusCode(HttpStatus.FORBIDDEN);        response.getHeaders().add("Content-Type", "application/json; charset=UTF-8");        log.info("url no right: {}", exchange.getRequest().getPath());        HashMap map = new HashMap<>();        map.put("code", "-1002");        map.put("message", "资源路径无访问权限!");        DataBuffer dataBuffer = response.bufferFactory().wrap(JSON.toJSONBytes(map));        return response.writeWith(Mono.just(dataBuffer));    }}

2.4.5 自定义成功退出登录的回调ServerLogoutSuccessHandler

用于自定义退出登录是的返回数据格式,示例代码如下:

package com.cloudservice.gateway_service.security;import java.util.HashMap;import org.springframework.core.io.buffer.DataBuffer;import org.springframework.http.HttpStatus;import org.springframework.http.server.reactive.ServerHttpResponse;import org.springframework.security.core.Authentication;import org.springframework.security.web.server.WebFilterExchange;import org.springframework.security.web.server.authentication.logout.ServerLogoutSuccessHandler;import org.springframework.stereotype.Component;import com.alibaba.fastjson.JSON;import lombok.extern.slf4j.Slf4j;import reactor.core.publisher.Mono;@Slf4j@Componentpublic class CustomLogoutSuccessHandler implements ServerLogoutSuccessHandler {@Override    public Mono onLogoutSuccess(WebFilterExchange exchange, Authentication authentication) {        ServerHttpResponse response = exchange.getExchange().getResponse();        response.setStatusCode(HttpStatus.OK);        response.getHeaders().add("Content-Type", "application/json; charset=UTF-8");        log.info("user logout success: {}", authentication.getName());        HashMap map = new HashMap<>();        map.put("code", "0");        map.put("message", "退出登录成功!");        DataBuffer dataBuffer = response.bufferFactory().wrap(JSON.toJSONBytes(map));        return response.writeWith(Mono.just(dataBuffer));    }}

2.4.6 最终配置类引用上述自定义回调的修改

package com.cloudservice.gateway_service.security;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;import org.springframework.security.config.web.server.ServerHttpSecurity;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.crypto.password.PasswordEncoder;import org.springframework.security.web.server.SecurityWebFilterChain;@Configuration@EnableWebFluxSecuritypublic class GatewaySecurityConfig {  @Bean  public PasswordEncoder passwordEncoder() {    return new BCryptPasswordEncoder();  }  @Autowired  private GatewayReactiveAuthorizationManager gatewayReactiveAuthorizationManager;  @Autowired  private CustomLoginFailureHandler customLoginFailureHandler;  @Autowired   private CustomLoginSuccessHandler customLoginSuccessHandler;  @Autowired  private CustomNoLoginHandler customNoLoginHandler;  @Autowired  private CustomLogoutSuccessHandler customLogoutSuccessHandler;  @Autowired  private CustomUrlNoRightHandler customUrlNoRightHandler;  @Bean  public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {    http      .authorizeExchange()        .pathMatchers("/favicon.ico", "/login", "/logout").permitAll()        .anyExchange().access(gatewayReactiveAuthorizationManager)      .and().formLogin()      .authenticationFailureHandler(customLoginFailureHandler)      .authenticationSuccessHandler(customLoginSuccessHandler)      .and().exceptionHandling()        .accessDeniedHandler(customUrlNoRightHandler)        .authenticationEntryPoint(customNoLoginHandler)      .and().logout().logoutSuccessHandler(customLogoutSuccessHandler)      .and().csrf().disable();    return http.build();  }}

【注意】

1. 登录会话的超时配置,可以修改nacos配置,加上:

server:
  reactive:
    session:
      timeout: 1m # session超时时间为1分钟, 默认是60分钟

2. 为了防止集中登录导致的登录数据库过载,修改GatewayReactiveUserDetailsService类的findByUsername接口实现,引入redis,优先查看redis缓存里有没有用户信息,有则从redis中加载,否则才从mysql数据库中加载

[上一篇]从零开始搭建高负载java架构(04)——gateway网关节点(动态路由)

[下一篇]从零开始搭建高负载java架构(06):gateway网关节点(sentinel篇)

参考资料:

[1]Spring Security详细讲解(JWT+SpringSecurity登入案例)

[2]Spring Security核心类简介

[3]在 webflux 环境中使用 Spring Security

转载请注明:文章转载自 http://www.konglu.com/
免责声明:

我们致力于保护作者版权,注重分享,被刊用文章【从零开始搭建高负载java架构(05)——gateway网关节点(权限验证篇)】因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理,本文部分文字与图片资源来自于网络,转载此文是出于传递更多信息之目的,若有来源标注错误或侵犯了您的合法权益,请立即通知我们,情况属实,我们会第一时间予以删除,并同时向您表示歉意,谢谢!

我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2023 成都空麓科技有限公司

ICP备案号:蜀ICP备2023000828号-2