token登录的实现

token登录的实现

我这种token只是简单的实现token,就是后端利用UUID 生成简单随机码,利用随机码作为在Redis中的键,然后存储的用户信息作为值,在每次合理请求的时候对token的有效时间进行刷新(利用拦截器),以确保用户信息的有效性。

为什么要用token

使用令牌(Token)进行身份验证和授权是一种常见的方式,特别适用于分布式和跨域请求的应用程序。

1. 为什么要使用 Token:

  • 无状态性:Token 身份验证是无状态的,不需要在服务器端存储会话信息。每个请求都包含了身份信息,因此服务器不需要维护状态。
  • 跨域支持:Token 可以轻松处理跨域请求,因为令牌可以在 HTTP 请求的头部(通常是 Authorization 头部)中传递,而不受同源策略的限制。
  • 扩展性:Token 可以包含任意信息,因此可以用于传递用户权限、角色、过期时间等信息。

2. Token 使用逻辑:

  • 用户登录成功后,生成一个 Token 并将用户信息存储在服务器端(如 Redis)以便快速验证和获取用户信息。
  • 向前端返回 Token。
  • 前端将 Token 存储在本地(通常是 sessionStorage 或 localStorage)。
  • 在每个后续的请求中,前端将 Token 通过请求头(通常是 Authorization 头)发送给后端。
  • 后端从请求头中获取 Token,验证其合法性,并使用 Token 获取用户信息。

后端(Spring Boot)示例:

定义login接口

@GetMapping("/login")
    public BaseResponse<String> login(String username,String password){
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getUsername,username);
        User one = userService.getOne(lambdaQueryWrapper);
        if(one == null){
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForHash().putAll("test:user:"+token, BeanUtil.beanToMap(one));
        redisTemplate.expire("test:user:" + token,2, TimeUnit.MINUTES);
        return ResultUtils.success(token);
    }

定义一个获取用户信息的其他接口

@GetMapping("/get")
    public BaseResponse<User> get(){
        return ResultUtils.success(UserHolder.getValue());
    }

创建拦截器:

public class LoginInterceptor implements HandlerInterceptor {
    private RedisTemplate<String,Object> redisTemplate;
    public LoginInterceptor(RedisTemplate<String,Object> template){
        this.redisTemplate = template;
    }
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        // 获取 session
        String token = request.getHeader("Authorization");
                // 检查用户是否已登录
        User user = new User();
        BeanUtil.fillBeanWithMap(redisTemplate.opsForHash().entries("test:user:"+token),user,false);
        if(user == null|| BeanUtil.isEmpty(user)){
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        redisTemplate.expire("test:user:"+token,2, TimeUnit.MINUTES);
        // 将用户数据存储到 ThreadLocal 中,以便在整个请求周期内访问
        UserHolder.setValue(user);
        // 进行其他逻辑验证,根据需求自行添加
        return true; // 允许请求继续执行
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        // 在请求处理之后执行,可以对 ModelAndView 进行修改
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        // 在请求完成之后执行,用于资源清理等操作

        // 清理 ThreadLocal 中的用户数据,防止内存泄漏
        UserHolder.clear();
    }

注册拦截器:

@Configuration
public class MvcConfig implements WebMvcConfigurer {
    @Resource
    private RedisTemplate<String,Object> redisTemplate;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 登录拦截器
        registry.addInterceptor(new LoginInterceptor(redisTemplate))
                .addPathPatterns("/**").excludePathPatterns("/user/login");
    }
}

使用结果截图

结果返回了一个token,这个token前端拿到以后要保存到sessionStorage或者LocalStorage里面,再把这个token送到请求头中,就可以啦

在这里插入图片描述

另一个请求:

设置请求头

设置Authorization
在这里插入图片描述
然后发起就可以得到啦
在这里插入图片描述

如果没有authorization就是得到未登录结果

在这里插入图片描述

前端(Vue.js)示例:

<!-- Login.vue -->
<template>
  <div>
    <input v-model="username" placeholder="Username" />
    <input type="password" v-model="password" placeholder="Password" />
    <button @click="login">Login</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      username: '',
      password: ''
    };
  },
  methods: {
    login() {
      // 发送登录请求,获取 Token
      axios.post('/api/user/login', { username: this.username, password: this.password })
        .then(response => {
          const token = response.data.token;
          // 存储 Token 到 sessionStorage
          sessionStorage.setItem('token', token);
          // 跳转到其他页面或进行其他操作
        })
        .catch(error => {
          console.error('Login failed:', error);
        });
    }
  }
};
</script>
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 在 PHP 中实现 token 登录需要以下步骤: 1. 在用户登录时,服务器端需要验证用户的身份信息(例如用户名和密码)。 2. 如果用户身份验证通过,服务器端将生成一个 token。这个 token 会包含一些用户的信息(例如用户 ID),并使用密钥进行加密。 3. 服务器端将这个 token 返回给客户端,客户端将 token 保存在本地(例如浏览器的 cookie 中)。 4. 在客户端发起请求时,会将 token 一并发送给服务器端。服务器端使用密钥解密 token,并校验 token 的合法性。如果 token 合法,则表示用户已登录;如果 token 不合法,则表示用户未登录。 下面是一个简单的 PHP 代码示例,展示了如何生成和校验 token: ``` <?php // 密钥 $secret = 'your-secret-key'; // 用户信息 $user = [ 'id' => 123, 'username' => 'john', ]; // 生成 token $header = [ 'alg' => 'HS256', 'typ' => 'JWT', ]; $payload = [ 'sub' => $user['id'], 'iat' => time(), 'exp' => time() + 3600, // 过期时间为 1 小时 ]; $header = base64_encode(json_encode($header)); $payload = base64_encode(json_encode($payload)); $signature = hash_hmac('sha256', "$header.$payload", $secret, true); $signature = base64_encode($signature); $token ### 回答2: PHP实现Token登录可以通过以下步骤来实现: 1. 首先,生成Token:在用户登录成功后,通过调用一些生成Token的函数来生成一个唯一的字符串。可以使用PHP的内置函数如`md5()`或`uniqid()`来生成Token。 2. 将Token保存到数据库中:将生成的Token与用户信息关联起来,并将其存储到数据库中的用户表中。可以在用户表中新建一个字段来存储Token信息。 3. 将Token返回给客户端:在生成Token并存储到数据库后,将Token返回给客户端。可以通过将Token作为响应的一部分以JSON格式返回给客户端。 4. 客户端存储Token:客户端在收到Token后,可以将其存储到Cookie或者本地存储中。这样可以在之后的请求中将Token作为认证凭证发送给服务器。 5. 验证Token:在每次请求中,服务器需要验证客户端发送过来的Token的有效性。可以通过查询数据库,检查Token是否存在且匹配用户信息。 6. Token过期处理:可以通过设置Token的有效期或者设置定期过期机制来处理过期Token。当Token过期时,需要重新生成Token并更新用户表中的Token字段。 7. 注销Token:在用户注销或者退出登录时,应该将Token从客户端和服务器端同时删除。可以通过清除Cookie或者删除本地存储中的Token实现。 通过以上步骤,可以使用PHP实现Token登录,提高系统的安全性和用户的使用体验。 ### 回答3: 在PHP中实现token登录是一种常见的身份验证机制。Token是一个包含用户信息和签名的字符串,用于验证用户的身份和权限。 实现token登录主要可以分为以下几个步骤: 1. 用户登录:用户使用用户名和密码进行登录,验证成功后生成一个token,并将token存储到服务器端和返回给客户端。 2. Token生成:在服务器端生成一个token,可以使用一些加密技术如HMAC(基于密钥的消息认证码)算法,将用户的信息和一些固定的或随机的字符串组合起来生成一个唯一的token。 3. Token存储:将token存储到服务器端,可以选择将token存储到数据库、缓存中或者直接存储到服务器的内存中。 4. Token验证:当用户进行后续请求时,将token作为参数或者HTTP头部的一部分发送到服务器,服务器端接收到token后,进行验证。验证可以通过比较接收到的token与存储的token是否一致,以及检查token的有效期等方式来进行。 5. Token刷新:为避免token的滥用,可以设置token的有效期,并在一定时间后要求用户进行重新验证。当token过期时,用户可以使用存储在客户端的refresh token来刷新token,即生成一个新的token。 通过以上步骤,可以实现token登录的功能,并提供一种安全、高效的身份验证方法,避免了传统的基于会话的认证方式中需要保存用户状态的问题。同时,token登录还具有跨平台、跨语言的特性,使得不同系统之间的身份验证更加简便。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xwhking

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值