【问题标题】:Is there any way to validate token before execution of rest api using spring在使用spring执行rest api之前有什么方法可以验证令牌
【发布时间】:2016-05-29 04:27:42
【问题描述】:

我已经为 rest 控制器配置了 spring boot。 我创建了许多 api,但我需要在乞求时验证每个 api 中的令牌信息,用户是否已授权或不基于提供的令牌。

在登录期间,我正在生成令牌,该令牌在每个 api 中都需要用于访问信息。如果令牌无效,那么我需要返回消息Sorry, your provided token information has been expired or not exists.

下面是我的api。

@RequestMapping(value="/delete", method= RequestMethod.DELETE)
public Map<String, Object> delete(@RequestBody String reqData,HttpServletRequest request) {
    Map<String, Object> m1 = new HashMap<String,Object>();
    JSONObject jsonData = new JSONObject(reqData);
    Token token= tokenDao.getByTokenCode(jsonData.getString("token"));
    if(token==null){
        m1.put("status", "error");
        m1.put("message", "Sorry, your provided token information expired or not exists.");
        return m1;
    }
    //here my logic to remove user from database.
}

有没有办法检查服务方法中的令牌功能或使用注释,所以我需要在每个 api 中删除相同的代码并需要使用一个通用功能。

【问题讨论】:

    标签: java spring rest spring-security spring-boot


    【解决方案1】:

    您可以使用 HandlerInterceptor 来处理您的令牌。

    HandlerInterceptor.preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 将在任何 RequestMapping 之前执行。

    preHandle中验证您的令牌。如果令牌有效,则继续,否则抛出异常,控制器建议将处理其余部分。

    暴露 MappedInterceptor 的 bean 类,spring 会自动加载 HandlerInterceptor bean 包含的内容。

    ControllerAdviceExceptionHandler 可以捕获异常并返回错误信息

    完整示例

    @RestController
    @EnableAutoConfiguration
    public class App {
    
        @RequestMapping("/")
        public String index() {
            return "hello world";
        }
    
        public static void main(String[] args) {
            SpringApplication.run(App.class, args);
        }
    
        public static class MyException extends RuntimeException {
    
        }
    
        @Bean
        @Autowired
        public MappedInterceptor getMappedInterceptor(MyHandlerInterceptor myHandlerInterceptor) {
            return new MappedInterceptor(new String[] { "/" }, myHandlerInterceptor);
        }
    
        @Component
        public static class TestBean {
            public boolean judgeToken(HttpServletRequest request) {
                String token = request.getParameter("token");
                if (token == null) {
                    throw new MyException();
                }
                return true;
            }
        }
    
        @Component
        public static class MyHandlerInterceptor implements HandlerInterceptor {
    
            @Autowired
            TestBean testBean;
    
            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                    throws Exception {
                return testBean.judgeToken(request);
            }
    
            @Override
            public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                    ModelAndView modelAndView) throws Exception {
    
            }
    
            @Override
            public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                    Exception ex) throws Exception {
    
            }
        }
    
        @ControllerAdvice
        public static class MyExceptionHandler {
            @ExceptionHandler(MyException.class)
            @ResponseBody
            public Map<String, Object> handelr() {
                Map<String, Object> m1 = new HashMap<String, Object>();
                m1.put("status", "error");
                m1.put("message", "Sorry, your provided token information expired or not exists.");
                return m1;
            }
        }
    
    }
    

    【讨论】:

    • 太棒了;它为我工作,但有什么方法可以检查选定的 api,因为某些 api 无需令牌即可访问。
    • 您可以为 MappedInterceptor 设置 includePatterns 和 excludePatterns。这些模式将为您过滤请求映射。
    【解决方案2】:
    public class TokenVallidation
     {        
        public static boolean tokenValidation(user id, String token){    
            Token token= tokenDao.getByTokenCode(id,jsonData.getString("token"));
            if(token==null){
                m1.put("status", "error");
                m1.put("message", "Sorry, your provided token information expired or not exists.");
                return false;
            }     
            else{
                return true;
            }
        }
    }
    

    对于控制器传递用户 ID 和令牌并检查令牌。您需要根据user id 参数更新dao 方法。

    【讨论】:

    • 我可以扩展或用作您证明类的注释吗?
    【解决方案3】:

    您可以使用缓存,而不是从数据库中获取令牌并与当前令牌匹配。创建您自己的缓存对象,如Map 或静态string,它将具有最新的令牌。您可以直接将传入的令牌与缓存中的此令牌进行比较。无需每次都访问数据库。

    【讨论】:

    • 我是 Spring 新手,在这里我为每个用户生成新的令牌。所以我们需要在每个 api 中验证这一点。客户端应用程序提供的令牌是否有效?
    • 令牌应仅在服务器端进行验证。您不能将您的验证码分享给客户端。
    • 我在每个 api 中都进行相同的验证,但我需要为此创建单独的方法并在每个 api 中使用。该方法自动检查令牌状态,如果有效则执行 api 代码,否则直接从常用方法返回消息。
    • 所以想为所有用户和api编写另一个方法对吗?
    • 是的,我需要创建一个可以在 api 代码执行之前首先检查的通用方法/服务/注释。
    猜你喜欢
    • 2014-02-02
    • 2019-02-14
    • 2021-09-04
    • 2016-01-01
    • 1970-01-01
    • 2020-09-20
    • 1970-01-01
    • 2014-02-21
    • 1970-01-01
    相关资源
    最近更新 更多