SpringBoot单体用户登录校验

一、概述

  要做一个有私有空间的单体的SpringBoot项目,用户的权限校验是必须得。需要指定哪些接口需要权限才能访问,哪些接口不需要权限就能访问。

  目标:

    1.用户登录、注册不需要权限校验,获取用户信息需要权限校验

    2.获取用户信息通过token来获取(从token中取出用户id)

    3.使用JWT来生成token

    4.使用拦截器来做权限校验

二、实例

  1.在pom.xml中导入jwt

     <!--引入jwt-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.10.3</version>
        </dependency>
        <!--注解-->
        <dependency>
            <groupId>org.jetbrains</groupId>
            <artifactId>annotations</artifactId>
            <version>RELEASE</version>
        </dependency>

 

  2.创建拦截器,用于拦截接口,并且给不同的接口设置不同的权限(是否验证后才能登录)

    a.创建一个拦截器,让其实现HandlerInterceptor

@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    /**
     * 进入到controller之前的拦截器
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //跳过跨域的请求
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            return true;
        }
        String accesToken = request.getHeader("token");
        if (accesToken == null) {
            accesToken = request.getParameter("token");
        }
//        JWTUtils.getUserIdByToken(accesToken);
        return checkToken(request,accesToken);
    }

    /**
     * 校验token 只要校验不通过 则会抛出异常
     *
     * @param token
     * @return
     */
    private boolean checkToken(HttpServletRequest request,String token) {
        if (StringUtils.isEmpty(token)) {
            throw new TokenException("TOKEN_IS_NULL");
        }
        try {
            DecodedJWT decodedJWT = JWTUtils.verify(token);
            Integer id = decodedJWT.getClaim("id").asInt();
            log.info("得到了用户id:{}", id);
            request.setAttribute("id",id);
            return true;
        } catch (SignatureVerificationException e) {
            log.info("签名不一致");
            throw new TokenException("TOKEN_IS_NOT_EQUALS");
        } catch (TokenExpiredException e) {
            log.info("令牌过期");
            throw new TokenException("TOKEN_ALREADY_EXPIRE");
        } catch (AlgorithmMismatchException e) {
            log.info("算法不匹配");
            throw new TokenException("TOKEN_SF_BPP");
        } catch (InvalidClaimException e) {
            log.info("失效的payload");
            throw new TokenException("TOKEN_PAYLOAD_SX");
        } catch (Exception e) {
            log.info("token无效");
            throw new TokenException("TOKEN_WX");
        }
    }


    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

  b.创建一个拦截器的配置监听(Spring容器会自动注入此配置,在addInterceptors方法中设置需要拦截的接口,和不需要拦截的接口就行了)

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Bean
    LoginInterceptor loginInterceptor() {
        return new LoginInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //拦截全部
        registry.addInterceptor(loginInterceptor())
                .addPathPatterns("/api/v1/pri/*/*/**")//把所有的priv都拦截掉
                .excludePathPatterns("/api/v1/pri/user/login","api/v1/pri/user/register");//登录和注册不拦截
        WebMvcConfigurer.super.addInterceptors(registry);
    }
}

 

  3.从token中拿到用户id

    在LoginInterceptor.java中有下面一段代码,通过HttpServletRequest把从token中得到的用户id设置到request.setAttribute中,使用的时候通过request.getAttribute("id")就可以拿到用户id

    下面是设置id的方法

    DecodedJWT decodedJWT = JWTUtils.verify(token);
            Integer id = decodedJWT.getClaim("id").asInt();
            log.info("得到了用户id:{}", id);
            request.setAttribute("id",id);
            return true;

    下面是得到用户id的方法,我们以获取用户信息为例

 /**
     * 根据用户的token,从token中取出用户id,然后通过用户id查询用户详情
     * @param request
     * @return
     */
    @GetMapping("info")
    public ResultOk getUserById(HttpServletRequest request) {
        Integer userId = (Integer) request.getAttribute("id");
        if (userId == null) throw new RuntimeException("用户id为空");
        return userService.getUserById(userId);
    }

  

  总结:好了,单体应用的简单的权限校验到这里就结束了。记录一下,万一以后用得上呢

 

posted on 2023-09-14 10:52  飘杨......  阅读(67)  评论(0编辑  收藏  举报