网站开发还是软件开发山西公司网站建设

当前位置: 首页 > news >正文

网站开发还是软件开发,山西公司网站建设,局域网视频网站搭建,电子商务网站建设感想文章目录 0. 网关如何处理登录请求1. Controller1.1. 获取用户信息1.2. 创建用户的token 2. Service2.1. FeignClient远程查询用户信息2.2. 验证密码 3. 何时刷新 token#xff0c;如何刷新【本文重点】 本文主要是分析登录请求 /login 的过程。 调用过程是#xff1a;ruoyi-… 文章目录 0. 网关如何处理登录请求1. Controller1.1. 获取用户信息1.2. 创建用户的token 2. Service2.1. FeignClient远程查询用户信息2.2. 验证密码 3. 何时刷新 token如何刷新【本文重点】 本文主要是分析登录请求 /login 的过程。 调用过程是ruoyi-auth — ruoyi-system

  1. 网关如何处理登录请求 登录请求 127.0.0.1:8080/auth/login是特殊的请求。经过的过滤器有 AuthFilter(order-200) XssFilter(order-100) CacheRequestFilter(order1) ValidateCodeFilter(order2) StripPrefix(order3)AuthFilter 认证过滤器对需要排除的 uri 地址不检查是否有 token 直接放行需要排除的配置可以在nacos中配置。默认配置如下

    安全配置

    security:# 验证码captcha:enabled: truetype: math# 防止XSS攻击xss:enabled: trueexcludeUrls:- /system/notice# 不校验白名单ignore:whites:- /auth/logout- /auth/login- /auth/register- /*/v2/api-docs- /csrf注意是“认证”不是“鉴权”认证主要是判断 token 是否有效不涉及权限

  2. Controller PostMapping(login)public R? login(RequestBody LoginBody form){// 用户登录LoginUser userInfo sysLoginService.login(form.getUsername(), form.getPassword());// 获取登录tokenreturn R.ok(tokenService.createToken(userInfo));}用户登录生成 token 返回 1.1. 获取用户信息 请看 Service 1.2. 创建用户的token 创建token返回给前端 /*** 创建令牌*/ public MapString, Object createToken(LoginUser loginUser) {String token IdUtils.fastUUID();// 1 封装用户信息Long userId loginUser.getSysUser().getUserId();String userName loginUser.getSysUser().getUserName();loginUser.setToken(token);loginUser.setUserid(userId);loginUser.setUsername(userName);loginUser.setIpaddr(IpUtils.getIpAddr());// 2 刷新tokenrefreshToken(loginUser);// 3 Jwt存储信息MapString, Object claimsMap new HashMapString, Object();claimsMap.put(SecurityConstants.USER_KEY, token);claimsMap.put(SecurityConstants.DETAILS_USER_ID, userId);claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName);// 接口返回信息MapString, Object rspMap new HashMapString, Object();rspMap.put(access_token, JwtUtils.createToken(claimsMap));rspMap.put(expires_in, expireTime);return rspMap; }在 1 处 把从 ruoyi-system 模块获取到的用户信息用户、角色、权限连同关键部分uuid、userId、userName重新封装 在 2 处 refreshToken方法负责刷新token。何时刷新、如何刷新是一个值得讨论的问题。在本文的第三章重点讨论了这个问题。 在 3 处 创建 token 的负载信息把 uuid、userId、userName 作为 token 的负载来创建 token。并返回给用户

  3. Service public LoginUser login(String username, String password){…// IP黑名单校验【在哪里初始化黑名单的】String blackStr Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST));if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())){recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, 很遗憾访问IP已被列入系统黑名单);throw new ServiceException(很遗憾访问IP已被列入系统黑名单);}// 查询用户信息RLoginUser userResult remoteUserService.getUserInfo(username, SecurityConstants.INNER);…passwordService.validate(user, password);return userInfo;}主要包括 2 个部分。 用 FeignCilent 从远程服务查询用户信息密码验证 注意 remoteUserService.getUserInfo(username, SecurityConstants.INNER) 的 INNER 指定了该请求是“内部”请求模块 auth 还会对 INNER 做处理。 2.1. FeignClient远程查询用户信息 以下代码com.ruoyi.system.api.RemoteUserService在 ruoyi-api-system 中只是定义了相关的 api 并不是实现。RuoYi 抽象了与系统相关的 ruoyi-api-system。在里面写公共的类或接口 FeignClient(contextId remoteUserService, value ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory RemoteUserFallbackFactory.class) public interface RemoteUserService {/*** 通过用户名查询用户信息** param username 用户名* param source 请求来源* return 结果*/GetMapping(/user/info/{username})public RLoginUser getUserInfo(PathVariable(username) String username, RequestHeader(SecurityConstants.FROM_SOURCE) String source); }url是/user/info/{username}。 调用服务是 ruoyi-system。 设置了降级 fallback 处理RemoteUserFallbackFactory 备注获取用户信息的详细分析参考https://www.yuque.com/yuchangyuan/tkb5br/vktircc4smqw8ggs 2.2. 验证密码 验证密码 主要是验证“可重试次数”和“密码正确性” 1、验证重试次数默认如果错误超过5次就锁定 10分钟 2、验证密码是否与数据库匹配。如登录成功需要清除密码错误次数。注册和验证密码用到的密码验证器要一致。

  4. 何时刷新 token如何刷新【本文重点】 何时刷新 只有在将要达到过期时间才会刷新来续期通常可以认为是 23 的时间点。 ① 调用refresh方法刷新refresh 接口 ② 创建 token 时createToken方法 ③ 设置用户信息时setLoginUser方法 ④ 验证 token 时verifyToken方法 主要是第四点。是通过 mvc 拦截器实现的 如何刷新 1、定时任务方案 ① 拦截用户请求保存 keyuserIdvalue需要刷新的时间点到一个全局的 map 中 ② 用 quartz 启动一个定时任务间隔一段时间扫描 map 来刷新 缺点不太好控制 2、拦截器方案 原理是通过 mvc 的拦截器 HandlerInterceptor 实现的。 为什么不通过过滤器实现而是拦截器 答案因为我们的目的不是要过滤掉请求而是拦截请求并根据条件设置token的过期时间 public class HeaderInterceptor implements AsyncHandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{……..String token SecurityUtils.getToken();if (StringUtils.isNotEmpty(token)){LoginUser loginUser AuthUtil.getLoginUser(token);if (StringUtils.isNotNull(loginUser)){// 验证和刷新 token 的过期时间AuthUtil.verifyLoginUserExpire(loginUser);SecurityContextHolder.set(SecurityConstants.LOGIN_USER, loginUser);}}return true;} }如上面的代码RuoYi 采用的也是拦截器方案在HeaderInterceptor拦截器中针对每个请求验证和刷新 token 的过期时间。详情参考https://www.yuque.com/yuchangyuan/tkb5br/d387fbc5d3f5522fa013b5e087a0dad9