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

做网站运维自己接单的平台

做网站运维,自己接单的平台,单位做好疫情防控工作,好123上网主页一、隐藏敏感信息 之前我们对 /user/me 路径,直接返回了登录的所有用户信息,其中的 passward 等敏感信息也会被返回到前端,这是很危险的,故我们需要选择性的返回用户信息,隐藏敏感用户信息 我们可以创建一个 UserDTO…

一、隐藏敏感信息

之前我们对 /user/me 路径,直接返回了登录的所有用户信息,其中的 passward 等敏感信息也会被返回到前端,这是很危险的,故我们需要选择性的返回用户信息,隐藏敏感用户信息

我们可以创建一个 UserDTO 类将 user 中可以返回的信息封装到其中后,将 UserDTO 返回

@Data
public class UserDTO {private Long id;private String nickName;private String icon;
}

然后我们将登录成功时,存入 user 的操作,改为存入 UserDTO ,这里使用的是 hutool 工具中 BeanUtil 来封装,将之前的 user 换成 UserDTO 后再存入 session 

        //保存用户登录信息
//        session.setAttribute("user",user);session.setAttribute("user", BeanUtil.copyProperties(user, UserDTO.class));

在拦截器进行登录校验时,我们会拿出这个 user ,需要将拦截器的对应代码也修改

    //前置拦截@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//拿到 session 中的 userObject user = request.getSession().getAttribute("user");System.out.println(user+"进入前置拦截器");//若用户不存在,拦截if(user == null){response.setStatus(401);//响应 401 状态码,表示未授权return false;}//将用户保存在 ThreadLocal 中,调用 UserHolder 中的静态方法UserHolder.saveUser((UserDTO) user);//放行System.out.println("前置拦截放行");return HandlerInterceptor.super.preHandle(request, response, handler);}
public class UserHolder {//user 对应的的线程池private static final ThreadLocal<UserDTO> tl = new ThreadLocal<>();//往线程池中存入用户public static void saveUser(UserDTO user){tl.set(user);}//拿到当前线程的 user,一个线程只有一个 userpublic static UserDTO getUser(){return tl.get();}//移除当前线程的 userpublic static void removeUser(){tl.remove();}}

修改完毕后,我们再次使用 postman 进行测试,完成发验证码,登录,等了校验三个请求

可以看到,这次返回的用户信息只含有 id,昵称,头像。保护了敏感信息。

二、解决集群的 session 共享问题

使用 session 进行登录信息的存储,当出现多台 tomcat 时,存储的信息会出现无法共享的情况,我们可以通过 Redis 来存储信息来解决

对于验证码,我们可以使用手机号作为 key 验证码存入 value中;

对于登录信息,我们可以使用哈希结构存储不同的信息,使用随机 token 生成随机且唯一的 key,在响应时,将 token 返回给浏览器,在之后需要用到 token 的请求,需要在请求中发送 token

在完成业务之前,我们先配置一下 redis 并测试是否可以正常访问

yml 配置文件:

server:port: 8082spring:application:name: mydpdatasource:url: jdbc:mysql://localhost:3306/learnbaseusername: rootpassword: 1234redis:host: 127.0.0.1port: 6379lettuce:pool:max-active: 8 # 最大连接max-idle: 8 # 最大空闲连接min-idle: 0max-wait: 100 # 最大等待时间,单位毫秒jackson:default-property-inclusion: non_null # JSON处理时忽略非空字段

测试 redis 是否连接正常

@SpringBootTest
class MyDianpingApplicationTests {@Resourceprivate StringRedisTemplate stringRedisTemplate;@Testvoid redisText() {stringRedisTemplate.opsForValue().set("dataRides","check");Object dataRides = stringRedisTemplate.opsForValue().get("dataRides");System.out.println(dataRides);}}

若 redis 中写入了键值对 dataRides , check 则可以认为连接时畅通的

接下来我们便可以通过 Redis 来优化登录业务了

发送验证码

首先在成员变量位置注入 StringRedisTemplate

    @Resourceprivate StringRedisTemplate stringRedisTemplate;

Controller 层和 UserService 接口无需改动,只需修改 UserServiceImpl 的 sendCode 方法即可

    @Overridepublic Result sendCode(String phone, HttpSession session) {//先用 hutool 工具校验手机号是否合法if (phone == null || !PhoneUtil.isPhone(phone)) {return Result.fail("请输入合法的手机号");//若不合法直接响应错误}//用 hutool 工具生成六位验证码String code = RandomUtil.randomNumbers(6);//将生成的验证码放入 session//TODO 优化:保存验证码到redis//TODO 后面两个参数时验证码的有效期,2分钟,设置后 redis 会在底层加上 set key value ex 120stringRedisTemplate.opsForValue().set("login:code:"+phone,code,2, TimeUnit.MINUTES);//给手机号发送验证码,这里模拟发送验证码的操作,而不是真正的发送System.out.println("手机收到了一条验证码短信:"+code);return Result.ok();}

登录逻辑

从 redis 中获取验证码并验证,验证通过后存入用户信息到 redis

生成 token 作为唯一的标识符,将用户信息封装为哈希表,将其挂在 token 下后存入 redis

最后返回 token ,在之后每次需要用到用户信息的请求中,我们都将 token 作为请求头发送请求

    @Overridepublic Result login(LoginFormDTO loginFormDTO, HttpSession session) {if(loginFormDTO == null){return Result.fail("无效操作");}//校验手机号String phone = loginFormDTO.getPhone();if (phone == null || !PhoneUtil.isPhone(phone)) {return Result.fail("请输入合法的手机号");//若不合法直接响应错误}//拿到 session 域中的验证码//TODO 优化:从 redis 中获取验证码String code1 = stringRedisTemplate.opsForValue().get("login:code:"+phone);String code = loginFormDTO.getCode();if(!code.equals(code1)){return Result.fail("验证码输入错误,请重新输入");}//验证码正确,判断是否存在用户User user = userMapper.selectByPhone(phone);if(user == null){//若不存在就创建一个用户并存入 mysqluser = createUserByPhone(phone);userMapper.insert(user);}//保存用户登录信息//TODO 优化:生成 token ,使用哈希的方式保存用户信息//使用 hutool 的 UUID 来生成 tokenString token = UUID.randomUUID().toString();UserDTO userDTO = BeanUtil.copyProperties(user,UserDTO.class);//使用 stringRedisTemplate,使用 hash 的方式存储存信息时必须保证所有 key value 都是 String 类型Map<String,String> userMap = new HashMap<>();userMap.put("id",Long.toString(userDTO.getId()));userMap.put("nickName",userDTO.getNickName());userMap.put("icon",userDTO.getIcon());stringRedisTemplate.opsForHash().putAll("login:token:"+token,userMap);//设置 token 有效日期,此处设定初始有效日期,可以通过通用拦截器更新有效日期stringRedisTemplate.expire("login:token:"+token,30,TimeUnit.MINUTES);//TODO 优化:返回生成的 tokenreturn Result.ok(token);}

 拦截器更新 token 有效期,登录验证

为了做到当用户完成任何操作后,token 的有效期更新,以保证用户的使用体验,我们可以设置一个全局拦截器,将 token 的更新操作写在全局拦截器中,并在全局拦截器中将用户信息存入线程池中

再使用第二级拦截器判断用户是否登录,登录的用户一定会存在于线程池,我们可以通过此来判断用户是否登录

一级拦截
public class RefreshTokenInterceptor implements HandlerInterceptor {//这个类没有被 Spring 管理,我们可以使用其配置类 MvcConfig 拿到后通过有参构造传递进来private StringRedisTemplate stringRedisTemplate;public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate){this.stringRedisTemplate = stringRedisTemplate;}//前置拦截@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//获取请求头中的 tokenString token = request.getHeader("authorization");if(StrUtil.isBlank(token)){//token 不存在,直接放行return true;}//基于 token 取用户信息Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries("login:token:"+token);if(userMap.isEmpty()){//没有信息,直接放行return true;}//有用户信息,将 userMap 转为 UserDTO 后保存到 ThreadLocal 中UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);//最后一个参数表示是否忽略转换过程中的错误UserHolder.saveUser(userDTO);//更新 token 的失效时间stringRedisTemplate.expire("login:token:"+token,30, TimeUnit.MINUTES);//放行return true;}//渲染后拦截@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {//在渲染后将 user 从线程中移除UserHolder.removeUser();}
}
二级拦截
public class LoginInterceptor implements HandlerInterceptor {//前置拦截@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//判断线程池中是否有登录用户,若没有则拦截,返回 401 状态码if(UserHolder.getUser() == null){response.setStatus(401);return false;}return true;}}

测试

http://www.hkea.cn/news/226901/

相关文章:

  • wordpress动态订单seo社区
  • 网站域没到期不能续费吗google谷歌搜索
  • 厦门好的做网站公司网络营销推广方式都有哪些
  • 重庆市建设工程信息官网站自己做网站的流程
  • 网站建设公司怎么做网络营销网站推广
  • 360应用商店seo服务套餐
  • 废橡胶网站建设个人博客网页设计
  • 什么网站做一手项目好域名查询官网
  • 做日用品的要找什么网站好站长工具端口检测
  • 贵州软件开发 网站开发手机版百度一下
  • 企业网站建立答辩问题百度怎么发布广告
  • 温州快建网站地推拉新接单网
  • 濉溪县城乡建设委员会燃气办网站热狗网站排名优化外包
  • 网站能不能自己做免费的seo教程
  • 湖南的商城网站建设优化教程网下载
  • 做网站需要哪些工程师西安seo诊断
  • tp做的网站封装成app2023北京封控了
  • 增城做网站要多少钱推广普通话手抄报
  • 石家庄网站系统开发智能搜索引擎
  • 迅速网站网络营销平台推广方案
  • 学前端要逛那些网站微信引流主动被加软件
  • 韩国flash网站免费手机网站建站平台
  • 东莞做网站卓诚网络昆明长尾词seo怎么优化
  • WordPress个性萌化插件郑州seo优化哪家好
  • 专业手机移动网站建设免费的seo优化
  • 西安网站建设王永杰域名注册 万网
  • 网站营销优化方案北京做的好的seo公司
  • 企业网站排名提升软件优化南宁seo优化
  • 创意合肥网站建设杭州seo公司排名
  • 网站专题页是什么中国十大关键词