You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于用户权限筛选对应域名的别名数据?前后端实现咨询

嘿,我来帮你梳理下这个权限控制的问题,还有你的代码是否合理,以及最优的实现方案~

问题分析与最优实现建议

核心需求很明确:用户只能访问与自身DOMAIN匹配的别名数据,所以我们要兼顾功能实现、代码复用性,更重要的是权限安全性。

你的现有代码思路是否合理?

先看你写的这段组件代码:

private getToken(): string {
  if (!this.token) {
    this.token = localStorage.getItem('usertoken');
  }
  return this.token;
}

getAliasesByDomain(){
  const token = this.getToken();
  let user;
  if (token) {
    user = token.split('.')[1];
    user = window.atob(user);
    user = JSON.parse(user);
    console.log('user z from getAliasesByDomain: '+user.domain);
    this.aliasesService.getAliasesByDomain(user.domain).subscribe(
      res => {
        console.log(res);
        this.alias = res;
      },
      err => console.error(err)
    );
  }
}

这个思路功能上是可行的,但有两个可以优化的点:

  1. 你已经在认证服务里实现了getUserDetails()方法,没必要在组件里重复写解析token的逻辑,直接复用更符合代码复用原则。
  2. 前端解析域名后传给API的方式存在安全隐患:用户可以通过浏览器调试工具篡改请求的domain参数,从而访问其他域名的别名数据,这会导致权限漏洞。

最优实现方案:后端权限校验+前端逻辑复用

1. 后端层面(关键!必须做)

前端传参的方式不安全,所以后端必须从JWT Token中解析用户信息,自动提取DOMAIN并过滤别名数据,完全不依赖前端传的参数。这样即使前端篡改请求,后端也能确保返回的数据是用户有权限访问的。

修改你的控制器和添加JWT验证中间件:

import jwt from 'jsonwebtoken';
import { NextFunction } from 'express';

// JWT验证中间件:解析token并挂载用户信息到请求对象
const authenticateToken = (req: Request, res: Response, next: NextFunction) => {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1]; // 提取Bearer后的token

  if (!token) {
    return res.status(401).json({ message: '未授权,请先登录' });
  }

  jwt.verify(token, process.env.SECRET_KEY as string, (err, user) => {
    if (err) {
      return res.status(403).json({ message: '无效的token' });
    }
    req.user = user as any; // 把解析后的用户信息挂载到req上
    next();
  });
};

// 修改后的别名列表接口:不再依赖req.params.domain,从token中取用户的domain
public async aliasesListByDomain(req: Request, res: Response): Promise<void> {
  const userDomain = req.user.DOMAIN; // 注意字段名要和JWT payload里的一致

  const aliasesListByDomain = await pool.query('SELECT * FROM virtual_aliases WHERE domain= ?', [userDomain]);
  if (aliasesListByDomain.length > 0) {
    res.json(aliasesListByDomain);
  } else {
    res.status(404).json({ message: "该域名下无别名数据" });
  }
}

// 路由添加中间件保护
router.get('/aliases', authenticateToken, aliasesController.aliasesListByDomain);

这样做的好处:

  • 彻底杜绝前端篡改参数的权限漏洞,权限控制完全由后端保障。
  • 前端请求时不需要传domain参数,简化了前端逻辑。

2. 前端层面(优化复用与逻辑清晰)

既然后端已经处理了权限过滤,前端只需要请求通用的别名列表接口,同时确保请求带上JWT Token即可。

首先修改别名服务:

// 不需要传domain参数,直接请求通用接口
getAliases(): Observable<Alias[]> {
  return this.http.get<Alias[]>(`${this.API_URI}/aliases`);
}

然后在组件里复用认证服务的getUserDetails()方法,调用修改后的服务:

getAliases() {
  const userDetails = this.authService.getUserDetails();
  if (userDetails) {
    // 这里可以做前端展示逻辑,比如显示当前用户的域名
    console.log('当前用户域名:', userDetails.DOMAIN);
    
    this.aliasesService.getAliases().subscribe(
      res => {
        this.alias = res;
      },
      err => {
        console.error('获取别名失败:', err);
        // 处理未授权错误,比如跳转到登录页
        if (err.status === 401 || err.status === 403) {
          this.authService.logout();
          this.router.navigate(['/login']);
        }
      }
    );
  } else {
    // 用户未登录,跳转到登录页
    this.router.navigate(['/login']);
  }
}

另外,建议添加一个HTTP拦截器,统一给所有需要认证的请求添加Authorization头,不用在每个服务里手动设置:

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(private authService: AuthService) {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    const token = this.authService.getToken();
    if (token) {
      request = request.clone({
        setHeaders: {
          Authorization: `Bearer ${token}`
        }
      });
    }
    return next.handle(request);
  }
}

然后在app.module.ts里注册这个拦截器:

import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { AuthInterceptor } from './auth.interceptor';

@NgModule({
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: AuthInterceptor,
      multi: true
    }
  ]
})
export class AppModule { }

总结

  1. 你原来的组件代码思路是对的,但存在安全隐患且重复了token解析逻辑,建议复用现有方法。
  2. 最优方案是后端从JWT中提取用户域名并过滤数据,前端只需要确保请求带上Token即可,既安全又简化了前端逻辑。
  3. 添加HTTP拦截器可以统一处理认证头,减少重复代码。

内容的提问来源于stack exchange,提问作者Defus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:36:26