后端登录功能实现——token技术
内容参考自以下博客:
https://www.yunliyunwai.cn/blog/detail/da87ec1283706f0c0995a9c235f2eb31(过度借鉴,请勿在意~)
【详细而又具体有逻辑的内容请直接点击链接访问,笔者只是一个过度的参考者+生疏的搬运工】
计时器参考以下博客:
https://www.yunliyunwai.cn/blog/detail/6df3b14ac972cbabf8484cd1c9da9554
【我不说我其实没写过…】
前端一点点内容参考自:
https://www.yunliyunwai.cn/blog/detail/529003da266b55e55d053affdc93baf4
为什么要使用token技术
- 利用token来解决登录验证之后页面与页面之间的联系的问题。
- 实现未登录用户(未携带token)不能访问其它重要页面的功能
- 简化后端其他功能访问数据库的请求操作,同时也更加安全化
第一次解决该问题时使用过session进行尝试
具体实现如下:
在登录的接口servlet中这样编写:
(前提:后端的个人信息展示和修改密码功能等需要通过session来获取已登录用户的id,方便对该用户对应数据库信息的CRUD)
//获取一个session对象
Http session = request.getSession();
//向session对象中存入user对象(或者id属性)
session.setAttribute("user",user);或
session.setAttribute("id",id);
在使用之后其它后端的功能界面时从session中获取id
//以字符串类型获取id
String id = String.valueOf(session.getAttribute("id"));
//转型为整型
Integer ID= Integer.valueOf(id);
这个session的技术代码看起来确实很简单,但是当时写的时候没有对接过,不太清楚它是否可以使用;后续学token的时候,接触到了token和session并行的技术,感觉这种方法好像不太行。
Session,Cookie,Token之间的联系和区别
Session 会话
众所周知,session就是一个会话,当用户在浏览某个网站的时候,从进入网站到浏览器关闭所经过的这段时间,也就是客户浏览这个网络所花费的时间,也就是说其实session是一个时间的概念,而每一个用户在登录之后都会有一个sessionID,服务端就是通过这个sessionID来辨别是否是同一个用户访问的这个网站。
相应的弊端也就随之出来了,SessionID是存储在服务器上的,当有大量的用户访问的时候,就会过分的占用服务器的资源。
Cookie
Cookie是保存在客户端的一系列的文本信息,它可以对特定的对象进行追踪,保存用户网页浏览记录和历史记录,使用cookie可以简化登录,但是cookie却是不允许跨域的,cookie也有泄露用户信息的问题所在。
Token(令牌)
定义
Token是在客户端频繁的向服务器进行请求数据时,服务器频繁的查询数据库的用户名和密码进行比对的情况下产生的
简单来说Token是一个绝对不会重复的字符串,Token作为一个令牌,当用户登录之后,后端将令牌返回给前端并保存到数据库,前端接收到token数据后保存到本地并放到请求头中随身携带便于之后一系列的后端请求时获取,如果某个用户未登录则不会有token值产生,当然也就不会携带。
下面这个看不太懂,应该是后端向数据库请求被简化和安全化了。
此后的一系列请求后端只需要带着这个令牌就可以前来请求数据,无需再带上用户名和密码,这样在大大提高效率的同时也能免除用户名和密码泄露的风险。
注意
笔者还是个后端小白,暂时还不会学长提到的计时器功能,redis技术也没有学过(尴尬)
实现
- token的生成
//导入UUID包
import java.util.UUID;
//service层生成随机token
String token = String.valueOf(UUID.randomUUID());
//并调用dao层保存token到数据库
return dao.storeTokenByTel(token,user);
-
方法解释:
UUID.randomUUID()
这个方法可以根据当前使用用户对象的内存,CPU等等一系列的数据情况来创建一个可以之间转化的字符串,从而保证token 绝对不可能重复。dao.storeTokenByTel(token,user)
方法利用service层传回的UUID值和servlet层接收到的user的属性值来更新数据库token字段
-
前端接收token
-
应该是从data里面获取的?
我不知道。 -
传递的时候是这样写滴~
-
//dao层方法中在存储完token后把所有前端登录时传递过来的数据和token一起存为一个集合list @Override //向数据库中插入UUID随机字符串作为token public List<User> storeTokenByTel(String token, User user) { Connection conn = JDBCUtil.getConnection(); PreparedStatement ptmt; String sql = "update user" + " set token = ? where user_tel=? "; User us; List<User> users=new ArrayList<>(); try { ptmt = conn.prepareStatement(sql); ptmt.setString(1, token); ptmt.setString(2,user.getUser_tel()); ptmt.execute(); us = new User(); //这里写这么多是因为这样才可以把token正常输出来,其他的数据会是0显示,我也不清楚是为什么....这里前端收到的数据还是有点问题... us.setUser_id(user.getUser_id()); us.setUser_name(user.getUser_name()); us.setName(user.getName()); us.setUser_tel(user.getUser_tel()); us.setPassword(user.getPassword()); us.setUser_id_type(user.getUser_id_type()); us.setToken(token); users.add(us); return users; ......
-
//servlet层将list转化为json格式传递给前端 String str=JSON.toJSONString(service.storeTokenByTel(newUser)); out.print(str);
-
-
-
前端传递token
-
需要将token放到请求头headers中
-
很大程度上保证数据传输的安全性
-
将获取的token存放在storage中
window.localStorage['token'] = JSON.stringify(res.data.token); //因为这个要正常的取出token数据,所以只用 out.write(token); //是不行的,它传回去会是一个字符串,所以按照上面的方法我改写成了list集合对象传回
-
-
后端取出token(笔者没有写过,不过其他后端同学都写过,看它们写的吧~)
-
//从请求头中取出来 String token = request.getHeader("token"); token = token.substring(token.indexOf("\"")+1,token.lastIndexOf("\"")); //控制台打印 System.out.pringln("前端传递的token令牌是:"+token);
- 大概就这样,具体的就不清楚了(…)
-
如果对你有帮助的话不要忘记一键三连噢~
谢谢鸭~
初次编写于2021/4/13日。