欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

荐 玩转 Spring boot 系列:(八)基于redis的用户登录注册以及过滤器的实现

程序员文章站 2022-03-26 21:20:10
前言:玩转 Spring boot 系列:(一)使用 Idea 搭建 Spring boot Maven 多模块父子工程(图解)玩转 Spring boot 系列:(二)配置多开发环境,集成druid数据源(图解)玩转 Spring boot 系列:(三)集成mybatis,实现增删改查(图解)玩转 Spring boot 系列:(四)mybatis 集成分页插件 pagehelper 并自定义分页结果集玩转 Spring boot 系列:(五)集成 redis 客户端 Jedis玩...

前言:

玩转 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的用户登录注册以及过滤器的实现都已经完成,可以根据自己的需要进行适当的增改。


创作不易,各位的支持和认可,就是我创作的最大动力,

【转载请联系本人】 如有问题,请联系我。欢迎斧正!不胜感激 !

求点赞