在Java中实现token登录上下文存储用户信息,可以使用Java Web框架(如Spring Boot)和JWT(JSON Web Token)来实现。
首先,需要引入相关依赖。在pom.xml文件中添加以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jwt-impl</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jwt-jackson</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
接下来,创建一个类来处理token的生成和验证逻辑。例如,创建一个名为TokenUtil的类:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class TokenUtil {
private static final String SECRET_KEY = "your_secret_key"; // 设置密钥
public String generateToken(String username) {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + 3600000); // 设置token过期时间为1小时
return Jwts.builder()
.setSubject(username)
.setIssuedAt(now)
.setExpiration(expiryDate)
.signWith(SignatureAlgorithm.HS512, SECRET_KEY)
.compact();
}
public String getUsernameFromToken(String token) {
Claims claims = Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
return claims.getSubject();
}
public boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token);
return true;
} catch (Exception e) {
return false;
}
}
}
接下来,在用户登录成功后,可以生成一个token并将其返回给客户端。例如,创建一个名为LoginController的类:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LoginController {
@Autowired
private TokenUtil tokenUtil;
@PostMapping("/login")
public String login(@RequestBody User user) {
// 验证用户名和密码
if (user.getUsername().equals("admin") && user.getPassword().equals("password")) {
// 登录成功,生成token
String token = tokenUtil.generateToken(user.getUsername());
// 如果用户信息量比较多,可以将用户信息存入非关系型数据库
//String userName = request.getHeader("username");
//String passWord = request.getHeader("password");
//UserInfoEntity user = new UserInfoEntity();
//user.setUsername(userName);
//redisTemplate.opsForValue().set(token , user);
return token;
} else {
// 登录失败
return "Invalid username or password";
}
}
}
1.在其他需要验证用户身份的请求中,可以使用拦截器或过滤器或AOP来验证token,并从token中获取用户信息。例如,创建一个名为AuthInterceptor的拦截器
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Autowired
private TokenUtil tokenUtil;
@Resource
private WebContext webContext;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 从请求头中获取token
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
token = token.substring(7); // 去掉"Bearer "前缀
// 验证token是否有效
if (tokenUtil.validateToken(token)) {
String username = tokenUtil.getUsernameFromToken(token);
// 将用户信息存储在上下文中,供后续使用
webContext.setCurrentUser(username);
return true;
}
}
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 返回401未授权状态码
return false;
}
}
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import sun.misc.Request;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
@Component
public class WebContext {
private static final String USER_ATTRIBUTES = "USER_ATTRIBUTES";
@Resource
private RedisUtil redisUtil;
/**
* Sets current user.
*
* @param user the user
*/
public void setCurrentUser(UserInfoEntity user) {
RequestContextHolder.currentRequestAttributes().setAttribute(USER_ATTRIBUTES, user, RequestAttributes.SCOPE_REQUEST);
}
/**
* Gets current user.
*
* @return the current user
*/
public UserInfoEntity getCurrentUser() {
UserInfoEntity user = (UserInfoEntity) RequestContextHolder.currentRequestAttributes().getAttribute(USER_ATTRIBUTES, RequestAttributes.SCOPE_REQUEST);
try {
if (null != user) {
return user;
} else {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
String token = request.getHeader("token");
user = (UserInfoEntity) redisUtil.get(token);
if (null == user) {
throw new LoginException(LoginExceptionEnum.NOT_LOGIN_ERROR.getCode(),
LoginExceptionEnum.NOT_LOGIN_ERROR.getDesc());
}
setCurrentUser(user);
return user;
}
} catch (LoginException e) {
e.printStackTrace();
throw new RuntimeException("");
}
}
}
采用aop的形式
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
@Slf4j
@Aspect
@Component
public class LoginAspect {
@Resource
private RedisUtil redisUtil;
@Resource
private WebContext webContext;
@Resource
RedisTemplate redisTemplate;
@Pointcut("execution(public * com.tairui.energy.controller.*.*(..)) " +
"&& !execution(public * com.tairui.energy.controller.LoginController.login(..))) ")
public void loginCheck() {
}
@Before("loginCheck()")
public void checkParam(JoinPoint pjp) throws Throwable {
// 接收到请求,记录请求内容
try {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String token = request.getHeader(BaseConstant.TOKEN);
if(token==null){
throw new LoginException(LoginExceptionEnum.NOT_LOGIN_ERROR.getCode(),
LoginExceptionEnum.NOT_LOGIN_ERROR.getDesc());
}
UserInfoEntity obj = (UserInfoEntity)redisUtil.get(token);
if (null == webContext.getCurrentUser()) {
webContext.setCurrentUser(obj);
}
if (Objects.isNull(obj)) {
log.error("************该用户TOKEN已过期!*************");
throw new LoginException(LoginExceptionEnum.NOT_LOGIN_ERROR.getCode(),
LoginExceptionEnum.NOT_LOGIN_ERROR.getDesc());
}
boolean set = redisUtil.expire(token, 1000 * 3600 * 4);
} catch (LoginException e) {
e.printStackTrace();
throw new LoginException(LoginExceptionEnum.NOT_LOGIN_ERROR.getCode(), e.getLocalizedMessage());
}
}
}
####最后,在需要获取用户信息的地方,可以通过UserContext类来获取当前登录用户的信息。
public class TestService {
@Resource
private WebContext webContext;
public void doSomething() {
String username = webContext.getUser();
// 使用username进行相应的操作...
}
}