【SpringBoot实现用户登录拦截】

SpringBoot实现用户登录拦截功能

使用JWT实现登录拦截的实现方式如下:

  • 创建一个工具类,实现生成token(密匙)、token(密匙)认证功能
  • 创建一个过滤器,对请求进行过滤,满足要求的请求才放行

在实现之前需要对项目添加依赖:

		<dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.6.0</version>
        </dependency>

工具类的实现

工具类主要提供两个方法:

  1. 生成token(密匙):依托JWT提供的方法实现
  2. token认证:对传入的token进行验证(加密以及时效性),并验证用户信息是否正确

工具类代码如下:
1.生成token

	/**
     * 登录后生成token
     * JWT_EXPIRE_TIME 是需要配置的Token过期时间,根据自己系统需要进行设置
     * JWT_KEY 是需要配置的加密串(相当于密码),需自定义
     * @param userId 用户id
     * @param userName 用户姓名
     * @return 返回生成的token
     */
	public String createToken(String userId,String userName){
        Map<String,Object> header = new HashMap<>();
        header.put("typ","JWT");
        header.put("alg","HS256");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.MILLISECOND, JWT_EXPIRE_TIME);
        //setID:用户ID
        //setExpiration:token过期时间  当前时间+有效时间
        //setSubject:用户名
        //setIssuedAt:token创建时间
        //signWith:加密方式
        JwtBuilder builder = Jwts.builder().setHeader(header)
                .setId(userId)
                .setExpiration(calendar.getTime())
                .setSubject(userName)
                .setIssuedAt(new Date())
                .signWith(SignatureAlgorithm.HS256,JWT_KEY);
        return builder.compact();
    }

2.验证token,其中BaseUserDDTO、BaseContext、BaseContextHolder、baseUserDAO、BaseException都是作者编写的项目中的变量,主要是验证通过后将用户信息保存到上线文环境中,供通过验证后进入的实际方法中的代码使用。

	/**
     * 验证token是否有效
     * @param token  请求头中携带的token
     * @return  token验证结果 false认证失败
     */
    public boolean verify(String token) {
        Claims claims;
        try {
            //token过期后,会抛出ExpiredJwtException 异常,通过这个来判定token过期,
            claims = Jwts.parser().setSigningKey(JWT_KEY).parseClaimsJws(token).getBody();
        } catch (ExpiredJwtException e){
            throw new BaseException(ErrorInfoConst.SYS_AUTH_TOKEN_OVERTIME);
        }
        //从token中获取用户id,查询该Id的用户是否存在,存在则token验证通过
        String id = claims.getId();
        // 查询登录用户信息
        BaseUserDDTO baseUserDDTO = jwtUtils.baseUserDAO.selectById(id);
        if (baseUserDDTO == null || baseUserDDTO.getUserId() == null) {
            throw new BaseException(ErrorInfoConst.SYS_AUTH_TOKEN_NOCURUSER);
        }
        BaseContext baseContext = BaseContextHolder.getContext();
        // 将查询出的数据放入上下文环境
        BaseCurrentUser baseCurrentUser = new BaseCurrentUser();
        baseCurrentUser.setUserId(baseUserDDTO.getUserId());
        baseCurrentUser.setUserName(baseUserDDTO.getUserName());
        baseCurrentUser.setOrgId(baseUserDDTO.getOrgId());
        baseCurrentUser.setOrgName(baseUserDDTO.getOrgName());
        baseCurrentUser.setUserLevel(baseUserDDTO.getUserLevel());
        baseCurrentUser.setUserType(baseUserDDTO.getUserType());
        baseContext.setBaseCurrentUser(baseCurrentUser);
        BaseContextHolder.setContext(baseContext);
        return true;
    }

过滤器的实现

过滤器的实现需要编写一个类实现HandlerInterceptor并注册到Spring上。代码如下:

// 通过注解注册到Spring中
@Component
public class AuthVerifyInterceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(AuthVerifyInterceptor.class);
	// 上一步中定义的工具类
    JwtUtils jwtUtils = new JwtUtils();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 这里实现校验
        // 跨域请求会首先发一个option请求,直接返回正常状态并通过拦截器
        if("OPTIONS".equals(request.getMethod())){
            response.setStatus(HttpServletResponse.SC_OK);
            return true;
        }
        response.setCharacterEncoding("utf-8");
        // 获取请求中携带的token
        if (request.getCookies() != null && request.getCookies()[0] != null) {
            Cookie[] cookies = request.getCookies();
            String token = null;
            for (Cookie item: cookies) {
                if ("TOKEN".equals(item.getName())) {
                    token = item.getValue();
                }
            }
            if (jwtUtils.verify(token)) {
                // 更新token
                BaseCurrentUser baseCurrentUser = BaseContextHolder.getContext().getBaseCurrentUser();
                token = jwtUtils.createToken(baseCurrentUser.getUserId(), baseCurrentUser.getUserName());
                if (result) {
                    Cookie cookie = new Cookie("TOKEN", token);
                    // 服务的地址,返回给前台保存Token使用的
                    cookie.setDomain("127.0.0.1");
                    cookie.setHttpOnly(false);
                    cookie.setPath("/");
                    response.addCookie(cookie);
                    return true;
                }
            }
        }
        return false;
    }
}

最后只需要在实现登录功能的代码中加上生成并返回Token的代码,就能实现登录拦截功能了。

设置白名单

有些时候有些地址不需要拦截,可以设置白名单,方式如下。
创建一个配置类,实现WebMvcConfigurer即可:

@Configuration
public class AuthVerifyConfiguration implements WebMvcConfigurer {

	// 刚刚实现的登录拦截类
    @Autowired
    protected AuthVerifyInterceptor authVerifyInterceptor;

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedHeaders("*")
                .allowedMethods("*")
                .allowedOriginPatterns("*")
                .allowCredentials(true);
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        List<String> excludePath = new ArrayList<>();
        //排除拦截,除了注册登录(此时还没token),其他都拦截
        excludePath.add("/web/auth/**");  //登录和注册
        excludePath.add("/doc.html");     //swagger
        excludePath.add("/swagger-ui.html");     //swagger
        excludePath.add("/swagger-ui.html#");     //swagger
        excludePath.add("/swagger-ui.html#/**");     //swagger
        excludePath.add("/webjars/**");     //swagger
        excludePath.add("/web/codegenerator/*");
        excludePath.add("/swagger-resources/**");     //swagger
        excludePath.add("/v2/api-docs");     //swagger
        registry.addInterceptor(authVerifyInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns(excludePath);
        WebMvcConfigurer.super.addInterceptors(registry);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值