0


SpringCloud整合GateWay+Sa-Token做登录验证(干货)

SpringCloud整合GateWay+Sa-Token做登录验证(干货)

一、什么是Sa-Token?

Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证权限认证单点登录OAuth2.0分布式Session会话微服务网关鉴权 等一系列权限相关问题,在这里我就不详细介绍了,想要了解的同学可以去查看官方文档 https://sa-token.cc/doc.html

二、关于GateWay

GateWay网关是我们服务的守门神,是统一入口处

核心功能特性:

1.请求路由:通过特定的规则将请求转发到对应的微服务

2.权限控制:进入不同微服务之前都要进行一个验证

3.限流:当请求流量过高时就要限流

在这里插入图片描述

在这里插入图片描述

三、具体步骤

项目结构

在这里插入图片描述

1、配置网关服务

在gateway模块引入依赖
<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>data_factory_cloud</artifactId><groupId>com.wjk</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>data_factory_cloud_gateway</artifactId><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>cn.dev33</groupId><artifactId>sa-token-reactor-spring-boot-starter</artifactId><version>1.34.0</version></dependency><!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) --><dependency><groupId>cn.dev33</groupId><artifactId>sa-token-dao-redis-jackson</artifactId><version>1.34.0</version></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- httpClient依赖,缺少此依赖api网关转发请求时可能发生503错误 --><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version></dependency><!--redis坐标       --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.9.0</version><!-- 请使用最新的版本号 --></dependency></dependencies></project>
在application.yml文件里面进行配置
server:port:10010spring:application:name: gateway

  cloud:nacos:server-addr: localhost:8848gateway:routes:-id: source_database
          uri: lb://source_database #负载均衡predicates:#路由断言,判断请求是否符合规则- Path=/sourceDatabase/**#路径断言,判断路径是否是以/user开头,如果是符合#          filters: #过滤器#            - AddRequestHeader=Truth,Itcast is freaking aowsome!-id: code
          uri: lb://code
          predicates:- Path=/code/**-id: user
          uri: lb://user
          predicates:- Path=/user/**-id: data_asset
          uri: lb://data_asset
          predicates:- Path=/dataAsset/**-id: data_standard
          uri: lb://data_standard
          predicates:- Path=/order/**-id: sourceApi
          uri: lb://data_standard
          predicates:- Path=/sourceApi/**redis:host: 192.168.246.133
    port:6379timeout: 10s
    #    password: 123456#    database: 0lettuce:pool:max-active:10max-wait:-1max-idle:16min-idle:8# Sa-Token配置sa-token:# token名称 (同时也是cookie名称)token-name: sa-token-authorization
  # token有效期,单位s 默认30天, -1代表永不过期timeout:2592000# token风格token-style: random-32# 是否尝试从 header 里读取 Tokenis-read-head:true# 是否开启自动续签auto-renew:true# 临时有效期,单位s,例如将其配置为 1800 (30分钟),代表用户如果30分钟无操作,则此Token会立即过期activity-timeout:-1# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时同端互斥)is-concurrent:true# 配置 Sa-Token 单独使用的 Redis 连接alone-redis:# Redis数据库索引(默认为0)database:0# Redis服务器地址host: 192.168.246.133
    # Redis服务器连接端口port:6379# Redis服务器连接密码(默认为空)#    password:# 连接超时时间timeout: 10s
新建类SaTokenConfigure,实现网关拦截
packagecom.wjk.config;importcn.dev33.satoken.config.SaTokenConfig;importcn.dev33.satoken.context.SaHolder;importcn.dev33.satoken.reactor.context.SaReactorSyncHolder;importcn.dev33.satoken.reactor.filter.SaReactorFilter;importcn.dev33.satoken.router.SaHttpMethod;importcn.dev33.satoken.router.SaRouter;importcn.dev33.satoken.stp.StpUtil;importcn.dev33.satoken.util.SaResult;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.Primary;importorg.springframework.web.server.ServerWebExchange;/**
 * @author YangBoss
 * @title: SaTokenConfigure
 * @projectName meta
 * @description: TODO
 * @date 2022/8/18 10:12
 */@ConfigurationpublicclassSaTokenConfigure{// 注册 Sa-Token全局过滤器@BeanpublicSaReactorFiltergetSaReactorFilter(){returnnewSaReactorFilter()// 拦截地址.addInclude("/**")// 开放地址.addExclude("/user/login").addExclude("/user/sendEmail").addExclude("/user/regist")// 鉴权方法:每次访问进入.setAuth(obj ->{// 登录校验 -- 拦截所有路由,并排除/user/doLogin 用于开放登录SaRouter.match("/**","/user/login", r ->StpUtil.checkLogin());SaRouter.match("/**","/user/regist", r ->StpUtil.checkLogin());SaRouter.match("/**","/user/sendEmail", r ->StpUtil.checkLogin());//                    // 角色认证 -- 拦截以 admin 开头的路由,必须具备 admin 角色或者 super-admin 角色才可以通过认证//                    SaRouter.match("/admin/**", r -> StpUtil.checkRoleOr("admin", "super-admin"));//                    // 权限认证 -- 不同模块, 校验不同权限//                    SaRouter.match("/meta-system/**", r -> StpUtil.checkPermission("system-no"));//                    SaRouter.match("/admin/**", r -> StpUtil.checkPermission("admin"));//                    SaRouter.match("/goods/**", r -> StpUtil.checkPermission("goods"));//                    SaRouter.match("/orders/**", r -> StpUtil.checkPermission("orders"));})// 异常处理方法:每次setAuth函数出现异常时进入.setError(e ->{// 设置错误返回格式为JSONServerWebExchange exchange =SaReactorSyncHolder.getContext();
                    exchange.getResponse().getHeaders().set("Content-Type","application/json; charset=utf-8");//                    return new ResultJsonUtil().fail(e.getMessage());returnSaResult.error(e.getMessage());}).setBeforeAuth(obj ->{// ---------- 设置跨域响应头 ----------SaHolder.getResponse()// 允许指定域访问跨域资源.setHeader("Access-Control-Allow-Origin","*")// 允许所有请求方式.setHeader("Access-Control-Allow-Methods","POST, GET, OPTIONS, DELETE")// 有效时间.setHeader("Access-Control-Max-Age","3600")// 允许的header参数.setHeader("Access-Control-Allow-Headers","*");// 如果是预检请求,则立即返回到前端SaRouter.match(SaHttpMethod.OPTIONS).free(r ->System.out.println("--------OPTIONS预检请求,不做处理")).back();});}}

2、配置用户服务

引入依赖
<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>data_factory_cloud</artifactId><groupId>com.wjk</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>data_factory_cloud_user</artifactId><dependencies><dependency><groupId>com.wjk</groupId><artifactId>data_factory_cloud_common</artifactId><version>1.0-SNAPSHOT</version></dependency><!-- sa-token权限认证框架 --><dependency><groupId>cn.dev33</groupId><artifactId>sa-token-spring-boot-starter</artifactId><version>1.37.0</version></dependency><!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) --><dependency><groupId>cn.dev33</groupId><artifactId>sa-token-redis-jackson</artifactId><version>1.37.0</version></dependency><!-- Spring Boot Starter Mail --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency></dependencies></project>

在yml文件里面配置

# Sa-Token配置sa-token:# token名称 (同时也是cookie名称)token-name: sa-token-authorization
  # token有效期,单位s 默认30天, -1代表永不过期timeout:3600# token风格token-style: random-32# 是否尝试从 header 里读取 Tokenis-read-head:true# 是否开启自动续签auto-renew:true# 临时有效期,单位s,例如将其配置为 1800 (30分钟),代表用户如果30分钟无操作,则此Token会立即过期activity-timeout:1800# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时同端互斥)is-concurrent:true# 配置 Sa-Token 单独使用的 Redis 连接alone-redis:# Redis数据库索引(默认为0)database:0# Redis服务器地址host: 192.168.246.133
    # Redis服务器连接端口port:6379# Redis服务器连接密码(默认为空)#    password:# 连接超时时间timeout: 30s
编写登录接口

UserService

packagecom.wjk.service;importcn.dev33.satoken.util.SaResult;importcom.baomidou.mybatisplus.extension.service.IService;importcom.wjk.entity.User;importcom.wjk.result.R;importcom.wjk.VO.UserVo;publicinterfaceUserServiceextendsIService<User>{//发送验证码邮件给指定邮箱RsendMimeMail(String email);//随机生成6位数字验证码StringrandomCode();//用户注册,验证验证码并保存用户信息Rregistered(UserVo userVo);//登录SaResultlogin(String email,String password)throwsException;//登出SaResultlogout();}

UserServiceImpl

@OverridepublicSaResultlogin(String email,String password)throwsException{//根据用户名从数据库中查询User user =this.getOne(Wrappers.lambdaQuery(User.class).eq(User::getEmail,email));System.out.println(user);if(user ==null){returnSaResult.error("用户名不存在");}//对登录密码进行加密boolean result =Md5Util.passwordVerify(password, user.getPassword(),Md5Util.md5Key);if(result){//根据用户id登录,第1步,先登录上StpUtil.login(user.getId());// 第2步,获取 Token  相关参数SaTokenInfo tokenInfo =StpUtil.getTokenInfo();// 第3步,返回给前端returnSaResult.data(tokenInfo);}returnSaResult.error("密码错误");}

User

packagecom.wjk.entity;importcom.baomidou.mybatisplus.annotation.IdType;importcom.baomidou.mybatisplus.annotation.TableField;importcom.baomidou.mybatisplus.annotation.TableId;importcom.baomidou.mybatisplus.annotation.TableName;importlombok.AllArgsConstructor;importlombok.Data;importlombok.NoArgsConstructor;importjava.util.Date;@TableName("users")@Data@NoArgsConstructor@AllArgsConstructorpublicclassUser{@TableId(value ="id",type =IdType.AUTO)privateInteger id;@TableField("username")privateString username;@TableField("password")privateString password;@TableField("email")privateString email;@TableField("created_at")privateDate createdAt;}

UserVo

packagecom.wjk.VO;importlombok.Data;@DatapublicclassUserVo{privateString username;privateString password;privateString email;//验证码privateString code;}

UserVoToUser

packagecom.wjk.VO;importcom.wjk.entity.User;publicclassUserVoToUser{/**
     * 将表单中的对象转化为数据库中存储的用户对象,剔除表单中的验证码字段。
     *
     * @param userVo 表单中的对象
     * @return 数据库中存储的用户对象
     */publicstaticUsertoUser(UserVo userVo){// 创建一个数据库中存储的对象User user =newUser();// 赋值
        user.setUsername(userVo.getUsername());
        user.setPassword(userVo.getPassword());
        user.setEmail(userVo.getEmail());// 返回转化后的对象return user;}}

MD5加密

packagecom.wjk.utils;importorg.apache.commons.codec.digest.DigestUtils;publicclassMd5Util{// 实现一个md5加解密publicfinalstaticString md5Key ="lalalalall";/**
     *
     * @param strPwd 明文密码
     * @param
     * @return 密文
     * @throws Exception
     *///用于注册时对密码进行加密publicstaticStringmd5(String strPwd,StringKey)throwsException{// 获取加密后的字符串String encodeStr =DigestUtils.md5Hex(strPwd +Key);//调用加密的算法return encodeStr;}/**
     * 用户登录,密码验证
     * @param pwdStr 明文字符串
     * @param oldPwd 密文字符串
     * @return
     */publicstaticbooleanpasswordVerify(String pwdStr,String oldPwd,String key)throwsException{//在该方法中,不需要在外面做密码加密,登录时获取到当前用户输入的密码,在方法里进行加密String md5Pwd=md5(pwdStr,key);if(md5Pwd.equalsIgnoreCase(oldPwd)){returntrue;}returnfalse;}}

controller

packagecom.wjk.controller;importcn.dev33.satoken.util.SaResult;importcom.wjk.service.UserService;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;importjavax.annotation.Resource;@RestController@RequestMapping("/user")publicclassLoginController{@ResourceprivateUserService userService;@GetMapping("/login")publicSaResultlogin(String email,String password)throwsException{return userService.login(email,password);}@GetMapping("/logout")publicSaResultlogout(){return userService.logout();}}
测试

发送验证码

在这里插入图片描述

根据验证码进行注册

在这里插入图片描述

登录

在这里插入图片描述

我这里的端口号10010对应的是gateway模块里的yml文件里面配置的端口号,这就是统一入口处,由它进行请求转发,肯定不止向登录模块请求转发,还会向别的端口进行,那么配置也跟上面一样,在gateway里面的yml文件里面要配置

gateway:routes:-id: source_database
          uri: lb://source_database
          predicates:#路由断言,判断请求是否符合规则- Path=/sourceDatabase/**#路径断言,判断路径是否是以/user开头,如果是符合#          filters: #过滤器#            - AddRequestHeader=Truth,Itcast is freaking aowsome!-id: code
          uri: lb://code
          predicates:- Path=/code/**-id: user
          uri: lb://user
          predicates:- Path=/user/**-id: data_asset
          uri: lb://data_asset
          predicates:- Path=/dataAsset/**-id: data_standard
          uri: lb://data_standard
          predicates:- Path=/order/**-id: sourceApi
          uri: lb://data_standard
          predicates:- Path=/sourceApi/**

该项目具体代码在gitee

https://gitee.com/wjk0321/data_factory_cloud

uri: lb://code
predicates:

  • Path=/code/**
  • id: user
    uri: lb://user
    predicates:
  • Path=/user/**
  • id: data_asset
    uri: lb://data_asset
    predicates:
  • Path=/dataAsset/**
  • id: data_standard
    uri: lb://data_standard
    predicates:
  • Path=/order/**
  • id: sourceApi
    uri: lb://data_standard
    predicates:
  • Path=/sourceApi/**

该项目具体代码在gitee

https://gitee.com/wjk0321/data_factory_cloud

本文转载自: https://blog.csdn.net/m0_73625251/article/details/139005155
版权归原作者 乔治Geroge 所有, 如有侵权,请联系我们删除。

“SpringCloud整合GateWay+Sa-Token做登录验证(干货)”的评论:

还没有评论