为了支持单用户多次登录和限制token数量,如何采用Redis的数据结构 Hash 和 List 实现?请说说你的思路
时间: 2023-06-01 09:05:33 浏览: 70
首先,使用Hash数据结构来存储用户信息,每个用户对应一个Hash,Hash存储用户登录信息和对应的token数量。键值对中键是用户名,值是一个对象,该对象存储用户的登录时间和token数量信息。例如:
```
hmset user:alice login_time 1563210600 token_count 2
```
然后,使用List数据结构来存储用户的token,以用户的用户名为key,存储该用户的所有token。例如:
```
lpush token:alice "token1"
lpush token:alice "token2"
```
在用户登录时,如果用户已经登录,则在该用户的token list中lpush一个新的token;如果该用户第一次登录,则hset一个新的Hash存储该用户信息。
在限制token数量时,每次用户登录时,先获取该用户的token数量,如果达到了限制数量,则将token list右侧多余的token使用ltrim删除。
以上是实现的基本思路,在实际应用中需要对细节进行调整和优化。
相关问题
使用 Spring Boot 和 Redis 实现用户登录后用户信息存储以及验证使用token当vaule
好的,以下是使用 Spring Boot 和 Redis 实现用户登录后用户信息存储以及验证使用 token 的步骤:
1. 首先需要在 pom.xml 中添加 Redis 相关的依赖,例如:jedis、spring-boot-starter-data-redis 等。
2. 在 application.properties 文件中配置 Redis 相关信息,如下:
```
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
```
3. 创建一个 UserService 类,用于操作 Redis 存储用户信息和 token。具体包括以下方法:
- saveUser(User user):将用户信息存储到 Redis 中。
- getUserById(String id):根据用户 id 从 Redis 中获取用户信息。
- deleteUserById(String id):根据用户 id 从 Redis 中删除用户信息。
- saveToken(String token, String userId):将 token 和用户 id 存储到 Redis 中。
- getUserIdByToken(String token):根据 token 从 Redis 中获取用户 id。
示例代码如下:
```
@Service
public class UserService {
@Autowired
private StringRedisTemplate redisTemplate;
private static final String REDIS_KEY_PREFIX_USER = "user:";
private static final String REDIS_KEY_PREFIX_LOGIN = "login:";
public void saveUser(User user) {
String key = REDIS_KEY_PREFIX_USER + user.getId();
redisTemplate.opsForHash().put(key, "id", user.getId());
redisTemplate.opsForHash().put(key, "username", user.getUsername());
redisTemplate.opsForHash().put(key, "password", user.getPassword());
}
public User getUserById(String id) {
String key = REDIS_KEY_PREFIX_USER + id;
String username = (String) redisTemplate.opsForHash().get(key, "username");
String password = (String) redisTemplate.opsForHash().get(key, "password");
User user = new User();
user.setId(id);
user.setUsername(username);
user.setPassword(password);
return user;
}
public void deleteUserById(String id) {
String key = REDIS_KEY_PREFIX_USER + id;
redisTemplate.delete(key);
}
public void saveToken(String token, String userId) {
redisTemplate.opsForValue().set(REDIS_KEY_PREFIX_LOGIN + token, userId, Duration.ofMinutes(30));
}
public String getUserIdByToken(String token) {
return redisTemplate.opsForValue().get(REDIS_KEY_PREFIX_LOGIN + token);
}
}
```
4. 在登录接口中,验证用户信息是否正确,并将 token 和用户 id 存储到 Redis 中。示例代码如下:
```
@RestController
public class LoginController {
@Autowired
private UserService userService;
@PostMapping("/login")
public String login(@RequestBody User user, HttpServletResponse response) {
// 验证用户信息是否正确
if (!"admin".equals(user.getUsername()) || !"123456".equals(user.getPassword())) {
return "用户名或密码错误";
}
// 将 token 和用户 id 存储到 Redis 中
String token = UUID.randomUUID().toString();
userService.saveToken(token, user.getId());
// 将 token 存储到 Cookie 中
Cookie cookie = new Cookie("token", token);
cookie.setMaxAge(30 * 60);
cookie.setPath("/");
response.addCookie(cookie);
return "登录成功";
}
}
```
5. 在需要验证用户信息的接口中,从 Redis 中获取用户信息,并验证用户是否已登录。示例代码如下:
```
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/user")
public String getUser(@RequestParam String userId, HttpServletRequest request) {
// 从 Redis 中获取用户信息
User user = userService.getUserById(userId);
if (user == null) {
return "用户不存在";
}
// 验证用户是否已登录
String token = null;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("token".equals(cookie.getName())) {
token = cookie.getValue();
break;
}
}
}
if (token == null) {
return "用户未登录";
}
String loginUserId = userService.getUserIdByToken(token);
if (!userId.equals(loginUserId)) {
return "用户未登录";
}
// TODO:返回用户信息
}
}
```
以上就是使用 Spring Boot 和 Redis 实现用户登录后用户信息存储以及验证使用 token 的步骤。
如何限制用户登录的token在redis中的缓存个数?
可以设置一个时间戳,每次用户登录成功后,将该时间戳作为键名,用户的 token 作为值存储在 Redis 中,同时将该时间戳存储在一个有序集合中,以时间戳作为分值,这样就可以按照时间顺序获取用户登录的 token。当缓存个数达到一定数量时,可以使用 Redis 的 ZREMRANGEBYSCORE 命令删除最旧的登录记录,保持缓存个数在一定范围内。