【问题标题】:Ask the server api before any request in Angular在 Angular 中的任何请求之前询问服务器 api
【发布时间】:2020-11-10 00:47:28
【问题描述】:

我将会话存储在数据库中,我有包含用户 ID、UUID 和到期日期的列。在来自 Angular 的任何请求之前,我想向 api 中的方法发送请求,该方法检查到期日期并让 angular 发送另一个请求(如果有效或注销用户)并删除带有令牌的本地存储以及关于我的会话到期日期的消息。我正在寻找与 HTTPInterceptor 类似的解决方案,它会自动将标头添加到每个请求中,而不是将标头添加到之前有请求的任何方法中。

我正在使用 Angular 10 和 Spring Boot 2.3.1。

编辑。

我找到了在 Angular 端的拦截器中捕获任何请求中的错误的解决方案。

@Injectable()
export class HttpInterceptorService implements HttpInterceptor {

  constructor() {}

  intercept(req: HttpRequest<any>, next: HttpHandler) {

    if (localStorage.getItem('username') && localStorage.getItem('basicauth')) {
      req = req.clone({
        setHeaders: {
          Authorization: localStorage.getItem('basicauth')
        }
      })
    }

    return next.handle(req).pipe(
      catchError(response => {

        console.log(response.status)
        // do something, example clear LocalStorage...

        return throwError(response);
      })
    )

  }
}

编辑 2。

我在 Spring-Boot 中使用 preHandle() 方法制作了拦截器,以在请求之前检查会话过期日期,如果会话过期,我将唯一响应状态设置为 495,它告诉 Angular 注销用户并清除 LocalStorage。

Spring-Boot 中的 preHandle() 方法:

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

    //if (request.getRequestURL().toString().endsWith("/api/basicauth"))
    String GUID = request.getHeader("GUID") == null? "1" : request.getHeader("GUID");

    if (sessionService.getSessionByGuid(GUID).isPresent()) {

        Session session = sessionService.getSessionByGuid(GUID).get();

        if(session.getExpirationDate().isBefore(LocalDateTime.now())) {

            sessionService.deleteSession(GUID);
            response.setStatus(495);

            return false;

        } else {

            sessionService.renewSession(session);
            return true;

        }

    }

    return true;
}

Angular 中的拦截器方法:

  intercept(req: HttpRequest<any>, next: HttpHandler) {

    if (localStorage.getItem('username') && localStorage.getItem('basicauth')) {
      req = req.clone({
        setHeaders: {
          Authorization: localStorage.getItem('basicauth'),
          GUID: localStorage.getItem('GUID')
        }
      })
    }

    return next.handle(req).pipe(
      catchError(response => {

        if (response.status == 495) {

          this.auth.removeSessionAndStorage();
          this.openSnackBar("Twoja sesja wygasłą!",);
          this.router.navigate(['login', 'session-expired']);

        }

        return throwError(response);
      })
    );

  }

【问题讨论】:

  • 这太低效了。只需发送您的请求,检查令牌,如果令牌过期并在此时重新验证,则响应 401。为自己节省往返服务器的时间。
  • @bryan60 并在错误部分清除我在subcribe 中的本地存储内容?
  • 可能会想在你的拦截器中使用catchError 运算符,然后检查状态码以了解要做什么。
  • @bryan60 你能看看我在 Angular 方面的解决方案吗?我编辑了帖子。
  • 这是我曾经做过的关于身份验证拦截器的回答:stackoverflow.com/questions/46017245/…

标签: java angular spring-boot request interceptor


【解决方案1】:

我认为你的设计有点缺陷。听起来您确实想要进行 JWT 身份验证,但是在实际执行并执行您的请求之前,您对令牌的验证方式感到困惑。

在你的拦截器中,只要你在每个请求中添加Authorization:Bearer &lt;token&gt;,你只需要在你的后端创建一些身份验证中间件。该中间件将检查每个请求的标头,获取 JWT 并对其进行验证。如果它是有效的,它就会跟进并执行请求。如果失败,它会返回 Unauthorized/Forbid 结果(取决于您想要返回的内容)。

有几种不同的设置方法,但这里有一篇不错的中型文章,描述了如何使用 Node.js 进行设置。其他一些框架,如 .NET,使其变得更容易。因此,您可能需要在选择一个选项之前评估这些选项。

文章中的示例代码:

let jwt = require('jsonwebtoken');
const config = require('./config.js');

let checkToken = (req, res, next) => {
  let token = req.headers['x-access-token'] || req.headers['authorization']; // Express headers are auto converted to lowercase
  if (token.startsWith('Bearer ')) {
    // Remove Bearer from string
    token = token.slice(7, token.length);
  }

  if (token) {
    jwt.verify(token, config.secret, (err, decoded) => {
      if (err) {
        return res.json({
          success: false,
          message: 'Token is not valid'
        });
      } else {
        req.decoded = decoded;
        next();
      }
    });
  } else {
    return res.json({
      success: false,
      message: 'Auth token is not supplied'
    });
  }
};

module.exports = {
  checkToken: checkToken
}

因此,基本上,您应该进行的过程由以下几项组成:

  1. 令牌作为标头与每个请求一起发送
  2. 后端存在一个中间件,用于在执行任何 API 方法之前验证令牌

https://medium.com/dev-bits/a-guide-for-adding-jwt-token-based-authentication-to-your-single-page-nodejs-applications-c403f7cf04f4

如果你坚持使用 Spring Boot,看起来有一些关于如何设置的示例代码here

【讨论】:

  • 您如何看待登录数据库后保存具有到期日期的 JWT,然后在 Spring Boot 中编写 interceptor 方法,该方法将在任何请求之前验证用户?
  • 您没有在请求之前验证用户。您使用请求验证它
  • 基本上,您认为每个请求有两个请求(一个用于验证用户,一个用于执行请求)的思维过程并不是一个好主意,原因有很多,但归根结底是效率和安全性。
  • 我知道,但安全是这个应用程序的首要任务。明天我会用结果编辑我的帖子。
  • 是的,您当前的设计在技术上不太安全。
猜你喜欢
  • 1970-01-01
  • 2019-01-15
  • 2016-04-16
  • 1970-01-01
  • 1970-01-01
  • 2015-12-16
  • 1970-01-01
  • 2020-10-26
  • 2014-05-06
相关资源
最近更新 更多