我这里使用的是SpringBoot工程,例子是一个登陆拦截请求头得例子。
例子中所用到的依赖:(自行根据需要添加)
<!--hutool开源工具类-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.5.2</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- lombok依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
自定义的返回格式:
/**
* 通用返回值
* @param <T>
*/
@Data
public class Result<T> {
//返回码
private Integer code;
//返回消息
private String message;
//返回数据
private T data;
// 私有化构造,无参构造
private Result() {}
// 返回数据 有参构造
public static <T> Result<T> build(T body, Integer code, String message) {
Result<T> result = new Result<>();
result.setData(body);
result.setCode(code);
result.setMessage(message);
return result;
}
}
按步骤来,直接可用版!
话不多说直接上代码!
1.创建自定义拦截器,用于拦截接口请求,获取请求头的token,并放到本地线程中。token是登陆成功后放到redis里的,下面我会说
/**
* 自定义拦截器
*/
@Component
public class LoginInterceptor implements HandlerInterceptor {
/**
* 在所有操纵之前执行
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1.获取请求方式,如果是options(预检请求)直接放行
String method = request.getMethod();
if ("OPTIONS".equals(method)){
return true;//如果是预检请求 直接放行
}
//2.从请求头获取token值,我这里把token放请求头了
String token = request.getHeader("token");
if (StrUtil.isEmpty(token)){
responseNoLoginInfo(response);//返回505友好提示
return false;
}
//3.拿获取到的token查询redis
String userInfo = redisTemplate.opsForValue().get("user:token" + token);
if (StrUtil.isEmpty(userInfo)){
responseNoLoginInfo(response);
return false;
}
//4.讲查询到的用户信息放到ThreadLocal线程中
ThreadLocalUtils.set(JSON.parseObject(userInfo, User.class));
//5.将redis用户过期时间更新,保证操作能正常完成
redisTemplate.expire("user:token"+token,30, TimeUnit.MINUTES);
//5.放行
return true;
}
/**
* 返回响应状态码 505
* @param response
*/
private void responseNoLoginInfo(HttpServletResponse response) {
Result<Object> result = Result.build(null,505,"");
PrintWriter writer = null;
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=utf-8");
try {
writer = response.getWriter();
writer.print(JSON.toJSONString(result));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (writer != null) writer.close();
}
}
/**
* 在所有操作之后执行
*
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
//删除本地线程ThreadLocal
ThreadLocalUtils.remove();
}
}
2.ThreadLocal工具类,用于添加、获取、删除token信息
public class ThreadLocalUtils{
//1.创建ThreadLocal线程对象
public static final ThreadLocal<User> threadLocal = new ThreadLocal<>();
/**
* 添加数据的方法
* @param User
*/
public static void set(User user) {
threadLocal.set(user);
}
/**
* 获取数据的方法
*/
public static User get() {
return threadLocal.get();
}
/**
* 删除数据的方法
*/
public static void remove() {
threadLocal.remove();
}
}
3.User类
@Data
public class User {
private String userName;
private String password;
}
4.MVC拦截器配置类
@Component
public class MvcConfig implements WebMvcConfigurer {
//注册拦截器
@Autowired
private LoginInterceptor loginInterceptor;
/**
* MVC解决跨域
* @param registry
* 我在这里直接解决跨域了,不然每个接口都要加注解
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")//添加规则路径
.allowCredentials(true)//允许跨域情况下传递cookie
.allowedOriginPatterns("*")//允许所有请求
.allowedMethods("*")//允许请求得方法
.allowedHeaders("*");//允许得请求头
}
/**
* 注册自定义拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor)//添加自定义拦截器
.excludePathPatterns("/login")//白名单路径,可添加多个用 用 "",隔开
.addPathPatterns("/**");//拦截所有
}
}
5.登陆接口、和获取用户信息接口
@RestController
public class Test{
//注入redis
@Autowired
private RedisTemplate redisTemplate;
/**
* 获取当前登陆用户信息
*/
@GetMapping("/getUserInfo")
public Result getUserInfo(){
//使用ThreadLocal后可以从拦截器获取token
return Result.build(AuthContextUtil.get(),200,"请求成功!");
}
/**
* 用户登录
* @return
*/
@PostMapping("/login")
public Result login(@RequestBody User user){
//获取用户名和密码
String userName = user.getUserName();
String password = user.getPassword();
//这里不做过多处理,直接生成token存redis
User user=new User();
user.setUserName(userName );
user.setPassword(password);
//这里token我用UUID
String token = UUID.randomUUID().toString().replaceAll("-", "");
//存redis,key:token value:字符串类型user对象 redisTemplate.opsForValue().set("user:token"+token,JSON.toJSONString(user),1, TimeUnit.DAYS);
return Result.build(user,200,"请求成功!");
}
}
测试自行测试,就不给例子了