푰’풎 풉풉품, 푰 풂풎 풂 품풓풂풅풖풂풕풆 풔풕풖풅풆풏풕 풇풓풐풎 푵풂풏풋풊풏품, 푪풉풊풏풂.
- 푺풉풄풐풐풍: 푯풐풉풂풊 푼풏풊풗풆풓풔풊풕풚
- 푳풆풂풓풏풊풏품: 푰’풎 풄풖풓풓풆풏풕풍풚 풍풆풂풓풏풊풏품 풅풆풔풊품풏 풑풂풕풕풆풓풏, 푳풆풆풕풄풐풅풆, 풅풊풔풕풓풊풃풖풕풆풅 풔풚풔풕풆풎, 풎풊풅풅풍풆풘풂풓풆 풂풏풅 풔풐 풐풏.
- 푯풐풘 풕풐 풓풆풂풄풉 풎풆:푽푿
- 푴풚 풃풍풐품: 풉풕풕풑풔://풉풉품풚풚풅풔.풃풍풐품.풄풔풅풏.풏풆풕/
- 푷풓풐풇풆풔풔풊풐풏풂풍 풔풌풊풍풍풔:풎풚 풅풓풆풂풎
感觉配置应该不是很麻烦,跟着官网走就行,如果你遇到问题,可以加链接上面的微信How to reach me那,加我我会帮你解决。
2:页面打开时获取的验证码接口:/code
我们打开F11 点进network里面就可以看到后台验证码接口/code,并且呢这个/code接口是在网关里面的,我们在网关处找到接口。
主要是这两个有关,这里没用传统的controller去写,而是通过另一种写法去完成了这个事情。这里也不用管它,我们点进创建code的过程。
但是先别急,在看code之前我们需要看一下网关的鉴权,里面有一个白名单。
初学者我们先不管这个鉴权是怎么做的,白名单从哪里来呢?可以看到,这里是从nacos的配置文件里面来的,我们看一眼nacos配置文件。
不难看出是读取的配置文件,然后组装成list,但是/code不在这个里面对不对,按道理来说应该拦截才对,为什么全局filter没有对它拦截呢?因为 gateway没有对/code这个路径配置过滤器,所以全局过滤器不作用在/code上,所谓的globalfilter只作用在配置过的所有路径上,全局是这个意思。如果不明白,请看:一文总结SpringCloud Gateway Filter过滤器(入门)及最佳实践 ,没有废话,继续回到ValidateCodeServiceImpl这个类上,看code处理代码。
这里有两种类型的验证码,数学和字符,开关还是跟之前一样,在配置文件中给出。不难看出,配置文件然后设置开关是一个比较常见的作用,同时可以看到哈,code是保存进redis中去的,并且维持是两分钟。获取验证码是比较简单的,接下来看验证码的验证。
3:登录直到出现界面一共是三个接口:
http://localhost:1024/dev-api/auth/login
http://localhost:1024/dev-api/system/user/getInfo
http://localhost:1024/dev-api/system/menu/getRouters
登录呢,就是另一个服务auth这个服务了,打开接口看看。怎么快速找到接口呢?推荐一个idea找接口的插件RestfumTool:
整个登录校验过程就是下面的这张图。跟着这个图看代码就可以了,总的来说这里是比较简单的。
但是有几个地方是要着重说的。
auth服务中的/login接口,调用的是system的userservice。
// 查询用户信息
R userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER);
通过之前的接口工具找到对应的方法:
内部服务调用校验
进去就会发现@InnerAuth 这个注解,这是一个springAOP注解。
自定义注解入门:
- https://segmentfault.com/a/1190000038172702
- https://juejin.cn/post/6844903949233815566
SpringAOP入门:
- https://www.cnblogs.com/cxuanBlog/p/13060510.html
如果没有看明白的话,可以再找点资料看看。
在调试之下,我们点进去可以发现,校验了头部中的from_source,所以fromsource是一个简单的来自内部的服务之间的校验,不过这里不是很安全,如果我手动加个header进去,也能访问对吧?并且下面的user校验,根据现有的代码不是很完善。当然默认的是不校验user用户的。之后就是正常的查询用户,权限。
token生成比较简单的,就是往redis中丢一个key:user的这样一个键值对,把user这个对象存进去。这个user是带有相关权限的。
验证完账号密码之后就会去获取已经登录的用户的信息。这个时候就不得不提gateway的Filter了,如果你不懂filter,首先请看我的filter入门链接:https://blog.csdn.net/qq_41376740/article/details/124724981?spm=1001.2014.3001.5501
首先访问接口要经过gateway,就要经过相关的filter的洗礼。看过配置就会发现,AuthFilter会作用在所有的路径上,包括/system/**,AuthFilter是一个全局授权验证或者说是已经登录过的验证。这个还是有点看头的。
CacheRequestFilter
主要是防止request中的body被读取一次之后就无法读取,这个代码没必要会。因为也就用这么一回,但是要知道它用处是什么。
AuthFilter
前端将令牌存进request header中的Authorization送到服务端,服务端在AuthFilter,对redis中的token进行校验,但是这里并没有进行token刷新的操作,redis是分布式登录状态的保存的地方。
首先要注意一点的就是,system中是包含security这个模块的,所以security中的bean也会被注入到里面,先看security中的相关结构:
HeaderInterceptor
HeaderInterceptor这个拦截器,会被注入进spring中去,那有人要问了,为什么这里只是一个单独的模块,为什么也能被扫描到呢?因为有spring.factories这个文件,它会把记录在里面的类都加入到spring容器中去,并且被识别。WebMvcConfig是拦截器配置的地方,可以看一下。
这个里面要说几个内容,一个是SecurityContextHolder的作用,点进去看,里面是用一个ThreadLocal的增强类做的一个线程级别的存储,目的是将user等对象存储进线程,因为一次完整的请求会由一个线程来完成,那么我想要在一次请求中的任意一个方法上如何获取某个对象呢?一直把对象放在方法的参数上,就比较呆了,ThreadLocal可以解决,把loginuser 登录过的对象存进去,目的就是在一次请求中任意位置都能获取到user对象。但是我觉得奇怪的是,这里二次在redis中判断了用户的登录状态,判断的同时对redis中的令牌进行了刷新。这里的二次判断状态是否有点多余?因为毕竟gateway网关已经做过一回了。但是吧,gateway和system是两个服务,system要想从gateway获得已经登录的user的信息,你就得gateway上面做文章,把user加入到http请求里面,所以不如再查一次redis?这只是我的想法,到底为什么我也不是很清楚。还有一个比较迷惑的事情就是,既然已经把user整个对象放进threadlocal里面了,那这些个头部的userId userName的意义在哪呢?等之后看看有啥用处吧。说不定之后的代码要用到。或许是为了减少redis中的读次数。
这个就没有太多可说的了,但是那个admin的判断,用id来判断如果不是一个admin的话,不太好,还是通过roles里面去判断比较ok。
这个接口是构建菜单的,基本就是从数据库里面读出来,然后把子菜单填充起来,然后加一点东西返回前端去回显,这个后端没有太多的技术,那些个大大小小的菜单类型我也没仔细看,可以后面用到的时候再看吧。
4:总结到这里一次登录到出现界面就结束了,之后我们就可以自己写代码,去填充那些接口,自己写一下再看若依怎么写,就挺不错的,适合练手,练练crud流程什么的。我也根据目前的这些完成了自己的登录改了一点小内容。可以看一下github,里面也有docker-compose的环境部署,release中的0.0.2就是
地址:https://github.com/21want28k/my_ruoyi



