IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 未经过token验证的用户A使用正常用户登录后的有效token访问A自己的资源 -> 正文阅读

[开发测试]未经过token验证的用户A使用正常用户登录后的有效token访问A自己的资源

用户ID和token:

已经登陆的用户:
{
    "status": 200,
    "msg": "登录成功!",
    "data": {
        "userId": "83c68099-6522-4d22-a841-7059089c18cd",
        "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6Ijgz
		YzY4MDk5LTY1MjItNGQyMi1hODQxLTcwNTkwODljMThjZCIsInR5cGUiOiLn
		lKjmiLciLCJleHAiOjE2NDY4MjA1MjgsImFjY291bnQiOiJhZW93dWd1b3poaS14eCJ9.QUuwS_24gJz7XxgHVUCDPGkGnp6j3e4p-lOHXpA_UeU"
    }
}

未进行登陆的用户:
userId:b3893569-94f2-420a-a3d3-827b6c8cafe6

在这里插入图片描述

使用未登录的用户ID登陆系统:
在这里插入图片描述
登陆一个正常使用的用户:
在这里插入图片描述

{
    "status": 200,
    "msg": "登录成功!",
    "data": {
        "userId": "83c68099-6522-4d22-a841-7059089c18cd",
        "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6Ijgz
		YzY4MDk5LTY1MjItNGQyMi1hODQxLTcwNTkwODljMThjZCIsInR5cGUiOiLn
        lKjmiLciLCJleHAiOjE2NDY4MjA1MjgsImFjY291bnQiOiJhZW93dWd1b3poaS14eC
        J9.QUuwS_24gJz7XxgHVUCDPGkGnp6j3e4p-lOHXpA_UeU"
    }
}

然后拿这个正常登录的用户的token去给未登录的用户进行token验证;
结果是拿到了未登录用户的个人信息。如下图A所示
图A

思考:为进行登录的用户可以拿着已经登录的用户的token进行访问自己的信息,这样河里吗?不河里!所以怎么办呢?
解决办法:
使用token里面PayLoad里的userId的信息,再次跟请求参数的userId验证一致性。
具体代码如下:
用户登录ServiceImpl:

    /**
     * 登陆用户,返回token。redis存放用户信息
     * @param account
     * @param password
     * @return token
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public Map<String,String> login(String account,String password) {
        try{
            QueryWrapper<User> wrapper = new QueryWrapper();
            wrapper.eq("account",account).eq("password",MD5Utils.md5(password));
            User userDB = userdao.selectOne(wrapper);
//            User userDB = userdao.selectUsersByAccountPassword(account,MD5Utils.md5(password));
            if(userDB != null){
                //添加负载 Payload 不要放用户敏感信息
                Map<String,String> Payload = new HashMap<>();
                Payload.put("id",userDB.getId());
                Payload.put("account",userDB.getAccount());
                Payload.put("type", UserTypeEnum.USER.getName());
                String token = JwtUtil.createJwtToken(Payload, 120);//设置负载,设置token过期时间 120minutes
                redisTemplate.opsForValue().set(User.class.getSimpleName() + "_"+ userDB.getId(), GsonUtil.getGson().toJson(userDB));
                Map<String,String>map = new HashMap<>();
                map.put("token",token);
                map.put("userId",userDB.getId());
                return map;
            }
            throw new MsgException("登陆失败,用户名或密码错误");
        }catch (MsgException e){
            throw e;
        }catch(RedisConnectionFailureException e){
            log.warn(e.getMessage(),e);
            throw new MsgException("Redis缓存连接失败!");
        } catch (Exception e){
            throw e;
        }
    }

LoginInterceptor登录拦截器,做token检查的

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//        boolean token = (boolean)request.getAttribute("token");
        try{
            String token = request.getHeader("token");
            if(token == null || token.equals("")){
                throw new MsgException("未携带token");
            }
            //验证token正确性和是否过期了。
            JwtUtil.verifyToken(token);
            return true;
        }catch (MsgException e){
            throw e;
        }catch (JWTDecodeException e){
            throw new MsgException("token过期,请重新登录");
        }catch (TokenExpiredException e){
            throw new MsgException("token过期,请重新登录");
        }
        catch (Exception e){
            throw e;
        }
    }

JudgeUserIdUtil: 从HttpServletRequest里面的Header取出token,在从token的Payload取出userId,对比传入的userId。

public class JudgeUserIdUtil {

    public static Boolean Judge(HttpServletRequest request,String userId){
        String token = request.getHeader("token");
        DecodedJWT decodedJWT = JwtUtil.verifyToken(token);
        String userIdInToken = decodedJWT.getClaim("id").asString();
        if(userId.equals(userIdInToken)){
            return true;
        }
        return false;
    }
}

代码修改完毕后,当未登录的用户使用别人登录后的token进行访问系统,图A再次发送请求,系统会提示非法请求。
在这里插入图片描述
总结:
1,登录的时候将用户ID放进去Payload里
2,然后如果一些request请求有userId参数,那就使用token里Payload里取出userId2,
3,userId参数和userId2进行对比,如果一致那就OK,如果不一致那就不允许访问。

PS:或许我们可以使用sa-token来解决这样的问题?博主未学习sa-token,不敢断言。
以上博文若有言辞不当,望诸君不吝赐教。

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2022-03-10 22:56:28  更:2022-03-10 22:57:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/18 2:39:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码