荐 玩转 Spring boot 系列:(八)基于redis的用户登录注册以及过滤器的实现
前言:
玩转 Spring boot 系列:(一)使用 Idea 搭建 Spring boot Maven 多模块父子工程(图解)
玩转 Spring boot 系列:(二)配置多开发环境,集成druid数据源(图解)
玩转 Spring boot 系列:(三)集成mybatis,实现增删改查(图解)
玩转 Spring boot 系列:(四)mybatis 集成分页插件 pagehelper 并自定义分页结果集
玩转 Spring boot 系列:(五)集成 redis 客户端 Jedis
玩转 Spring boot 系列:(六)优雅的全局异常处理 和通用响应器
玩转 Spring boot 系列:(七)集成七牛实现文件上传
spring boot 集成七牛实现文件上传之后,接下来我们实现基于redis的登录注册权限以及过滤器的实现
代码地址:Spring Boot 集成 基于redis的用户登录注册以及过滤器的实现
实现思路:在本项目中,我们默认拦截所有的请求,对静态文件、error页面 不予拦截。对controller方法中标记了 @IgnToken 注解予以放行。
1、更新父模块pom文件
<commons-collections4.version>4.4</commons-collections4.version>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>${commons-collections4.version}</version>
</dependency>
2、重写 WebMvcConfigurer 接口的 addInterceptors 方法:
import com.liren.admin.common.sys.interceptor.LoginHandlerInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* MVC配置
*
* @author: LiRen
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private LoginHandlerInterceptor loginHandlerInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginHandlerInterceptor)
.addPathPatterns("/**/**")
.excludePathPatterns("/static/**", "/error");
}
}
3、新建一个拦截器,拦截所有的请求,如果请求中标记有 @IgnToken 则不予检查token,其余的方法 要检测是否携带token。代码如下。
import com.alibaba.fastjson.JSON;
import com.liren.admin.common.sys.annotion.IgnToken;
import com.liren.admin.common.utils.redis.RedisUtil;
import com.liren.admin.entity.pojo.User;
import com.liren.basic.common.response.JsonReturn;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
/**
* @description: <h1>AuthorizationInterceptor 用户权限拦截器</h1>
* @author: LiRen
**/
@Slf4j
@Component
public class LoginHandlerInterceptor implements HandlerInterceptor {
public static final String HEAD = "token";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
IgnToken annotation;
if (handler instanceof HandlerMethod) {
annotation = ((HandlerMethod) handler).getMethodAnnotation(IgnToken.class);
if (annotation != null) {
return true;
}
} else {
return true;
}
// 获取用户凭证
String token = request.getHeader(HEAD);
if (StringUtils.isBlank(token)) {
token = request.getParameter(HEAD);
}
// 凭证为空
if (StringUtils.isBlank(token)) {
return this.resp(response, HttpStatus.UNAUTHORIZED.value(), header + "不能为空!");
}
// token不为空,开始获取用户数据
Map<String, Object> map = (Map<String, Object>) RedisUtil.getObjectValue(token);
if (MapUtils.isEmpty(map)) {
return this.resp(response, HttpStatus.UNAUTHORIZED.value(), header + "失效,请重新登录!");
}
User user = (User) map.get("user");
if (user == null) {
return this.resp(response, HttpStatus.UNAUTHORIZED.value(), header + "失效,请重新登录!");
}
return true;
}
private boolean resp(HttpServletResponse response, int value, String msg) throws IOException {
response.reset();
response.setContentType("application/json;charset=utf-8");
response.setCharacterEncoding("UTF-8");
JsonReturn r = new JsonReturn();
r.put("code", r.CODE_NO_LOGIN);
r.put("status", value);
r.put("msg", msg);
response.getWriter().print(JSON.toJSON(r));
return false;
}
}
4、@IgnToken注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 忽略登录效验
*
* @author: LiRen
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnToken {
}
5、对controller 方法标记 @IgnToken 注解
@IgnToken
@GetMapping("/testLogin/{userId}")
public JsonReturn testLogin(@PathVariable String userId) {
User user = myUserService.queryuserbyid(userId);
return JsonReturn.send(JsonReturn.CODE_SUCCESS, "请求成功", user);
}
6、获取token的接口,一般来说,我们要对 登录,退出,获取验证码的接口 进行放行,方法上添加 @IgnToken 注解
@IgnToken
@GetMapping("/userLogin")
public JsonReturn adminlogin(String userId) {
User user = myUserService.queryuserbyid(userId);
// 生成token
String token = TokenUtil.createToken(user);
log.info("token:{}", token);
return JsonReturn.send(JsonReturn.CODE_SUCCESS, "请求成功", token);
}
7、生成 token的方法
/**
* 生成token
*
* @author: LiRen
*/
public static String createToken(User user) {
String token = UUID.randomUUID().toString().replace("-", "") + "_" + user.getUserName();
Map<String, Object> map = new HashMap<>();
map.put("user", user);
map.put("token", token);
// map.put("权限,路径",);
RedisUtil.setExpireObject(token, tokenConfig.getExpire(), map);
return token;
}
8、application.yml
liren:
token:
# 加密秘钥
secret: my_secret[liren]
# token有效时长,8小时,单位秒
expire: 28800
header: token
9、tokenConfig.java
@Data
@Component
@ConfigurationProperties(prefix = "liren.token")
public class TokenConfig {
private String secret;
private Integer expire;
private String header;
}
10、RedisUtil.getObjectValue 方法
public static Object getObjectValue(String key) {
Jedis jedis = JedisUtil.getJedis();
Object o = new Object();
try {
SerializeUtil su = new SerializeUtil();
o = su.unserialize(jedis.get(key.getBytes()));
} finally {
JedisUtil.returnResource(jedis);
}
return o;
}
至此,基于redis的用户登录注册以及过滤器的实现都已经完成,可以根据自己的需要进行适当的增改。
创作不易,各位的支持和认可,就是我创作的最大动力,
【转载请联系本人】 如有问题,请联系我。欢迎斧正!不胜感激 !
求点赞
上一篇: 力扣题解| 1370. 上升下降字符串
下一篇: 线性分类器(CCF20200901)