如何用Azure Function(HTTP Trigger)为Angular4实现OAuth用户认证及解决授权问题
嘿,我之前也踩过Azure Functions里[Authorize]属性的坑,它和ASP.NET Core Web API里的用法不太一样,咱们一步步来解决你的问题:
1. 先理清Azure Functions身份验证的核心逻辑
Azure Functions的[Authorize]属性本身不会单独生效,它是依赖于函数应用层面的身份验证/授权配置的。默认情况下,函数应用允许匿名访问,所以就算你加了注解,也拦不住未授权请求。
2. 先开启函数应用的身份验证开关(关键第一步)
你得先在Azure门户里给函数应用配置基础身份验证规则:
- 进入你的Function App后台,找到左侧菜单的身份验证选项
- 点击添加身份验证提供程序,选择自定义(因为你要自己用Users表实现令牌验证)
- 在「请求未经过身份验证时要执行的操作」里选返回HTTP 401未授权,这样匿名请求会被先拦截
- 保存配置,这时候
[Authorize]属性才会真正开始起作用
3. 实现自定义令牌验证的完整流程
既然要基于自己的Users表做类似OAuth的令牌认证,需要分两步走:
第一步:写登录函数生成令牌
先做一个公开的登录接口,接收用户名密码,查询Users表验证身份,然后生成并返回自定义令牌(推荐用JWT,方便携带和验证):
[FunctionName("Login")] public static async Task<IActionResult> Login( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req, ILogger log) { var requestBody = await new StreamReader(req.Body).ReadToEndAsync(); var loginModel = JsonConvert.DeserializeObject<LoginModel>(requestBody); // 从Azure DB查询用户,验证密码(注意密码要哈希存储,别用明文) var user = await GetUserFromDatabase(loginModel.Username); if (user == null || !VerifyPassword(loginModel.Password, user.HashedPassword)) { return new UnauthorizedResult(); } // 生成JWT令牌,包含用户信息、过期时间等 var token = GenerateJwtToken(user); return new OkObjectResult(new { Token = token }); }
第二步:在受保护函数里验证令牌
给需要授权的函数加上[Authorize],同时手动验证请求头里的令牌(因为是自定义逻辑,需要自己校验合法性):
[FunctionName("GetUserProfile")] [Authorize] public static async Task<IActionResult> GetUserProfile( [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req, ILogger log) { // 从请求头提取令牌 var token = req.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last(); if (string.IsNullOrEmpty(token)) { return new UnauthorizedResult(); } // 验证令牌:检查签名、过期时间,关联到Users表的有效用户 var isValid = ValidateJwtToken(token); if (!isValid) { return new UnauthorizedResult(); } // 执行业务逻辑,返回用户数据 var userProfile = await GetUserProfileFromDatabase(token); return new OkObjectResult(userProfile); }
如果觉得每个函数都写验证太麻烦,也可以做一个自定义身份验证中间件,把令牌验证逻辑统一抽离出来。
4. Angular端的请求处理
登录成功后把令牌存在本地存储,然后用HTTP拦截器自动给所有请求带上Authorization头:
@Injectable() export class AuthInterceptor implements HttpInterceptor { intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const authToken = localStorage.getItem('authToken'); if (authToken) { request = request.clone({ setHeaders: { Authorization: `Bearer ${authToken}` } }); } return next.handle(request); } }
记得把这个拦截器注册到你的Angular模块里,这样所有请求都会自动携带令牌。
常见坑点提醒
- 别搞混
AuthorizationLevel和[Authorize]:HttpTrigger里的AuthorizationLevel要设为Anonymous,因为我们靠函数应用的身份验证拦截请求,而不是Azure内置的Function/Admin级别授权 - 令牌一定要加过期时间,避免永久有效
- Users表的密码必须用哈希算法(比如BCrypt)存储,绝对不能存明文
内容的提问来源于stack exchange,提问作者Muhammad Fuzail Zubari
相关产品推荐
相关产品推荐

