在登录的过程中为什么要有token的存在呢?
在登录功能中使用 token 的主要目的是为了实现用户身份验证和授权管理。使用 token 可以帮助系统实现以下功能:
身份验证: 用户在登录成功后会收到一个包含 token 的响应。之后,用户每次请求需要在请求头中携带该 token,服务端可以根据 token 来验证用户的身份和权限。
状态管理: 通过 token 可以实现状态无关性,即服务端不需要存储用户的登录状态。每次请求都携带 token,服务端可以根据 token 来识别用户身份,而不需要在服务端存储用户的登录状态。
安全性: 使用 token 可以增加系统的安全性。通过合适的算法和密钥进行 token 签名,可以防止 token 被伪造,从而保护用户数据的安全。
权限管理: 通过 token 可以实现对用户访问权限的管理。在 token 中可以包含用户的角色信息或者权限信息,服务端可以根据 token 中的信息来判断用户是否有权限进行特定操作。
跨平台支持: token 可以在不同的客户端和服务端间进行传递,因此支持跨平台的登录验证。
综上所述,使用 token 可以简化系统的状态管理,增强安全性,实现权限管理,并支持跨平台的用户验证,是一种常见且有效的用户认证和授权方式。
那么,在整个过程中,生辰token的具体流程是怎样的呢:流程图奉上
这个流程图看起来比较复杂,实际上只有生成token的规则和生成token之后的对其进行的处理两步操作,实现起来会非常简单。
该功能实现应用到的技术:springBoot + mybatis-plus + redis?
1.?
当我们在登录页面输入完成用户名和密码后,在用户名和密码都正确的情况下,发出请求
@RestController @RequestMapping("/login") @CrossOrigin public class LoginController{ @Autowired private UserService userService; /** * 登录 * user * * @param * @return */ @GetMapping(value = "/getUserInfo") public ResponseEntity<Map<String, String>> getUserInfo (String userCode,String password){ return userService.getUserInfo(userCode,password); }}
@Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { @Autowired private UserMapper userMapper; @Autowired private UserRoleJoinMapper join; @Resource private RedisTemplate redisTemplate; @Autowired private JavaMailSender mailSender; /** * 登录验证功能 * @param userCode * @param password * @return */ //ResponseEntity Spring框架的Web应用程序中常见的返回响应的方式 @Override public ResponseEntity<Map<String, String>> getUserInfo(String userCode, String password) { Map<String, String> response = new HashMap<>(); MPJLambdaWrapper<User> wrapper = new MPJLambdaWrapper<>(); wrapper.select(User::getUserId,User::getUserCode,User::getUserName,User::getPassword,User::getRoleId,User::getRegistrationTime, User::getEmail) .selectAs(Role::getRoleId,UserRoleJoin::getRoleId) .leftJoin(Role.class,Role::getRoleId,User::getRoleId); wrapper.eq("userCode",userCode); User user = join.selectOne(wrapper); //判断用户是否存在 if (null != user){ //用户存在,判断密码是否正确 if (password.equals(user.getPassword())) { // 生成Token String token = generateToken(userCode); //将token存入redies中 Map<String,String> userMap = new HashMap(); userMap.put("userName",user.getUserName()); userMap.put("passWord",user.getPassword()); userMap.put("email",user.getEmail()); userMap.put("roleId",user.getRoleId().toString()); userMap.put("userId",user.getUserId().toString()); userMap.put("registrationTime",user.getRegistrationTime().toString()); redisTemplate.opsForValue().set("token:"+token,userMap); response.put("token",token); return ResponseEntity.ok(response); }else { //返回一个HTTP 401状态码的响应 表示未经授权响应的ResponseEntity实例,并将其作为HTTP响应返回给客户端 return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } }else { response.put("msg","用户不存在"); //返回一个HTTP 401状态码的响应 表示未经授权响应的ResponseEntity实例,并将其作为HTTP响应返回给客户端 return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } }}
/** * 生成token的规则: * 生成随机的字符串 * 年月日时分秒+用户编码 * @param userCode * @return */ private String generateToken(String userCode) { //定义token String token = ""; //获取日期和时间 LocalDateTime now = LocalDateTime.now(); // 拼接年月日时分秒("%02d" 转换为两位数的字符串) String dataTimeString = now.getYear() + String.format("%02d", now.getMonthValue()) + String.format("%02d", now.getDayOfMonth()) + String.format("%02d", now.getHour()) + String.format("%02d", now.getMinute()) + String.format("%02d", now.getSecond()); Random random = new Random(); //随机生成5位数 int randomNumber = random.nextInt(90000) + 10000; String randomNum = Integer.toString(randomNumber); //拼接token token = token + dataTimeString + userCode + randomNum; return token; }
?实现类实现了生成token的具体流程,目前没有使用md5编码格式加密,方便存入redis中便于查看
?保存到redis中的格式: 将用户信息存入到以生成的token作为key的redis键值对中
注意:redis可视化工具使用了? ??RedisDesktopManager , 如果需要可在下方留言,我会做一期教程给大家
@Mapper public interface UserMapper extends BaseMapper<User> { }
以上为代码实现的流程,包括流程图中对于token的生成以及在redis中的操作
2.那么前端该如何处理呢,使用的前端技术是 vue+element-ui
这段代码对服务端返回的token进行了处理,将token保存到了localStaorage中?
可以使用F12进入调试模式,找到应用程序,可以在local storage 中找到存储的token?
3. 为什么本地要存到local storage中呢,那能不能存到cookie中呢?
Cookie和LocalStorage是Web开发中常用的客户端存储技术,它们有以下区别和作用:
存储容量:
Cookie:每个域名下的Cookie总大小通常限制为4KB左右。
LocalStorage:每个域名下的LocalStorage总大小通常限制为5MB或更大(具体取决于浏览器)。
生命周期:
Cookie:可以设置过期时间,使得数据在有效期内保持,也可以设置为会话Cookie,关闭浏览器后自动删除。
LocalStorage:除非被主动删除,否则数据会一直保存在浏览器中。
数据发送:
Cookie:每次请求都会将Cookie数据发送到服务器,增加网络传输量。
LocalStorage:数据不会自动发送到服务器,仅在客户端使用。
安全性:
Cookie:可以设置Secure标志以限制只在HTTPS连接中传输,但Cookie信息容易被窃取或篡改。
LocalStorage:仅在客户端使用,不会随请求发送到服务器,更安全。
使用方式:
Cookie:可以通过JavaScript的document.cookie
进行读写操作。
LocalStorage:可以通过JavaScript的localStorage
对象进行读写操作。
作用方面:
Cookie主要用于在客户端和服务器之间存储会话信息、身份验证、跟踪用户行为等。
LocalStorage主要用于本地存储用户的持久化数据,例如用户首选项、表单数据等。
综上所述,Cookie适合用于需要在客户端和服务器之间交互的场景,而LocalStorage适用于需要在客户端长期保存数据的场景
结论:local storage 和 cookie都可以使用,取决于客户端和服务端之间交互的使用场景