MSAL Angular 向已知的受保护资源提供一个 Interceptor 类,该类可自动为使用 Angular http 客户端的传出请求获取令牌。 本文档提供有关配置和使用 MsalInterceptor的详细信息。
虽然我们建议使用 MsalInterceptor,而不是直接使用 acquireTokenSilent API,但请注意,是否使用 MsalInterceptor 是可选的。 你可能希望改为使用 acquireToken API 显式获取令牌。
请注意,为方便起见提供, MsalInterceptor 可能不适合所有用例。 如果你有 MsalInterceptor 无法满足的特定需求,我们建议你编写自己的拦截器。
Configuration
在 app.module.ts 中配置 MsalInterceptor
可以在 app.module.ts 中将 MsalInterceptor 连同其配置一起添加到应用程序中,作为提供程序。 这些导入项引入了一个 MSAL 实例,以及两个 Angular 专用的配置对象。 第三个参数是一个 MsalInterceptorConfiguration 对象,其中包含 interactionType、protectedResourceMap 以及可选的 authRequest 的值。
配置可能如下所示。 有关为应用配置 MSAL Angular 的其他方法,请参阅我们的 配置文档 。
import { NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS, HttpClientModule } from "@angular/common/http";
import { AppComponent } from './app.component';
import { MsalModule, MsalRedirectComponent, MsalGuard, MsalInterceptor } from '@azure/msal-angular'; // Import MsalInterceptor
import { InteractionType, PublicClientApplication } from '@azure/msal-browser';
@NgModule({
declarations: [
AppComponent,
],
imports: [
MsalModule.forRoot( new PublicClientApplication({
// MSAL Configuration
}), {
// MSAL Guard Configuration
}, {
// MSAL Interceptor Configurations
interactionType: InteractionType.Redirect,
protectedResourceMap: new Map([
['Enter_the_Graph_Endpoint_Here/v1.0/me', ['user.read']]
])
})
],
providers: [
{
provide: HTTP_INTERCEPTORS, // Provides as HTTP Interceptor
useClass: MsalInterceptor,
multi: true
},
MsalGuard
],
bootstrap: [AppComponent, MsalRedirectComponent]
})
export class AppModule { }
交互类型
MsalInterceptor虽然设计为以无提示方式获取令牌,但当无提示请求失败时,它将回退到以交互方式获取令牌。
InteractionType可从@azure/msal-browser导入,并设置为Popup或Redirect。
{
interactionType: InteractionType.Redirect,
protectedResourceMap: new Map([
['Enter_the_Graph_Endpoint_Here/v1.0/me', ['user.read']]
])
}
受保护的资源映射
受保护的资源及其对应范围在 MsalInterceptor 配置中以 protectedResourceMap 的形式提供。
在 protectedResourceMap 集合中输入的 URL 区分大小写。 对于每个资源,添加所请求的、需要在访问令牌中返回的范围。
例如:
-
["user.read"]适用于 Microsoft Graph -
["<Application ID URL>/scope"]用于自定义 Web API(即api://<Application ID>/access_as_user)
可以通过以下方式为资源指定范围:
- 一组作用域,无论使用何种 HTTP 方法,这些作用域都会被添加到针对该资源的每个 HTTP 请求中。
{
interactionType: InteractionType.Redirect,
protectedResourceMap: new Map<string, Array<string> | null>([
["https://graph.microsoft.com/v1.0/me", ["user.read", "profile"]],
["https://myapplication.com/user/*", ["customscope.read"]]
]),
}
- 一个
ProtectedResourceScopes数组,它将仅为特定的 HTTP 方法附加作用域。
{
interactionType: InteractionType.Redirect,
protectedResourceMap: new Map<string, Array<string|ProtectedResourceScopes> | null>([
["https://graph.microsoft.com/v1.0/me", ["user.read"]],
["http://myapplication.com", [
{
httpMethod: "POST",
scopes: ["write.scope"]
}
]]
])
}
请注意,资源的范围可以包含字符串和 ProtectedResourceScopes。 在下面的示例中, GET 请求将具有范围 "all.scope" , "read.scope"而请求 PUT 将只具有 "all.scope"。
{
interactionType: InteractionType.Redirect,
protectedResourceMap: new Map<string, Array<string|ProtectedResourceScopes> | null>([
["http://myapplication.com", [
"all.scope",
{
httpMethod: "GET",
scopes: ["read.scope"]
},
{
httpMethod: "POST",
scopes: ["info.scope"]
}
]]
])
}
- 范围值
null,指示资源不受保护且不会获取令牌。 未包含在protectedResourceMap中的资源默认不受保护。 当某个资源中的部分路由需要保护,而部分路由不需要保护时,将特定资源设为不受保护会很有用。 请注意,protectedResourceMap中的顺序很重要,因此应将 null 资源放在任何类似的基础 URL 或通配符之前。
{
interactionType: InteractionType.Redirect,
protectedResourceMap: new Map<string, Array<string> | null>([
["https://graph.microsoft.com/v1.0/me", ["user.read", "profile"]],
["https://myapplication.com/unprotected", null],
["https://myapplication.com/unprotected/post", [{ httpMethod: 'POST', scopes: null }]],
["https://myapplication.com", ["custom.scope"]]
]),
}
关于 protectedResourceMap,还需注意以下几点:
-
通配符:
protectedResourceMap支持使用*作为通配符。 使用通配符时,如果在protectedResourceMap中找到多个匹配项,将使用找到的第一个匹配项(具体取决于protectedResourceMap的顺序)。 -
相对路径:如果应用程序中存在相对资源路径,则可能需要提供应用程序中
protectedResourceMap的相对路径。 这也适用于 ngx-translate 可能出现的问题。 请注意,根据你的应用程序不同,protectedResourceMap中的相对路径可能需要开头加斜杠,也可能不需要,因此可能需要两种写法都试一试。
严格匹配(strictMatching)
在 msal-angular v5 中,条目的 protectedResourceMap URL 组件模式匹配默认使用严格的匹配语义。
MsalInterceptorConfiguration 上的 strictMatching 字段控制此行为。
Important
如果应用程序动态设置 protectedResourceMap 键(例如,来自环境文件、APP_INITIALIZER 或 JSON 配置),并且这些键是不包含子路径或通配符的基础 URL,那么严格匹配可能会在无提示的情况下导致无法附加 Authorization 标头。 这会导致出现 401 错误,但不会在构建时出错,也不会针对每个请求发出警告;只有在未显式配置 strictMatching 的情况下,才会出现一次性的初始化警告。 有关详细信息,请参阅 故障排除严格匹配 。
严格匹配会带来哪些变化
| Behavior | 旧版 (strictMatching: false) |
严格(v5 中的默认值) |
|---|---|---|
| 元字符转义 |
. 和其他正则表达式元字符不会被转义;它们会作为正则表达式运算符起作用 |
所有元字符(包括 .)都被视为 文本 |
| 定位 | 模式可能与字符串中的任何位置匹配 | 模式必须与 完整字符串 匹配 (^…$) |
主机通配符 (*) |
* 匹配任何字符序列,包括 . |
* 匹配任何不包含 . 的任何字符序列(通配符仅限于单个 DNS 标签内) |
路径/搜索/哈希通配符 (*) |
* 匹配任何字符序列 |
* 匹配任何字符序列(未更改) |
? 字符 |
传递给基础正则表达式 | 被视为文本?(URL 查询字符串分隔符,而不是通配符) |
使用严格匹配(v5 默认值):
- 匹配
app.contoso.com但不a.b.contoso.com匹配(通配符不能跨越点分隔符)的类似于*.contoso.com的模式。 - 形如
https://graph.microsoft.com/v1.0/me的模式仅匹配该确切 URL。
常见故障模式
以下 protectedResourceMap 键模式在旧版匹配下可以正常工作,但在严格匹配下会静默失败:
| 密钥模式 | 传出请求 URL | 严格匹配下的结果 | 修复 |
|---|---|---|---|
https://api.example.com |
https://api.example.com/v1/users |
不匹配 — 键解析为路径 /,请求具有路径 /v1/users |
https://api.example.com/* |
https://api.example.com/ |
https://api.example.com/v1/users |
无匹配 - 尾部反斜杠将模式固定为精确/ |
https://api.example.com/* |
environment.apiConfig.uri(例如,https://api.example.com) |
https://api.example.com/v1/users |
不匹配 - 与上面相同 | `${environment.apiConfig.uri}/*` |
v5 中的默认行为(无需配置)
默认情况下启用严格匹配。 不需要其他配置:
{
interactionType: InteractionType.Redirect,
protectedResourceMap: new Map([
["https://*.contoso.com/api", ["contoso.scope"]],
["https://graph.microsoft.com/v1.0/me", ["user.read"]]
])
// strictMatching defaults to true in v5
}
选择不使用旧版匹配
如果您的模式依赖于 v4 中较宽松的匹配方式,您可以设置 strictMatching: false 以暂时保留旧版行为:
注释
为确保向后兼容性,提供了旧版匹配功能 (strictMatching: false),该功能可能会在未来的主要版本中被移除。 我们建议你更新 protectedResourceMap 模式,使其支持严格匹配。
{
interactionType: InteractionType.Redirect,
protectedResourceMap: new Map([
["https://*.contoso.com/api", ["contoso.scope"]],
["https://graph.microsoft.com/v1.0/me", ["user.read"]]
]),
strictMatching: false // Use legacy matching for backwards compatibility
}
环境驱动配置指南
如果您的 protectedResourceMap 键引用 Angular environment 值(例如 environment.apiConfig.uri),请检查这些值是精确路径(例如 https://graph.microsoft.com/v1.0/me)还是纯基 URL(例如 https://api.example.com)。 精确路径在严格匹配下也能正常工作,不需要特殊处理:
export function MSALInterceptorConfigFactory(): MsalInterceptorConfiguration {
const protectedResourceMap = new Map<string, Array<string>>();
// environment.apiConfig.uri is an exact path (e.g. "https://graph.microsoft.com/v1.0/me")
// — strict matching works correctly
protectedResourceMap.set(environment.apiConfig.uri, environment.apiConfig.scopes);
return {
interactionType: InteractionType.Redirect,
protectedResourceMap,
};
}
如果环境值是裸基 URL,并且需要匹配子路径,请追加 /* 通配符:
// environment.apiConfig.uri is a base URL (e.g. "https://api.example.com")
// Append /* to match all sub-paths
protectedResourceMap.set(`${environment.apiConfig.uri}/*`, environment.apiConfig.scopes);
对于那些在构建时无法确定键形状的真正动态配置(例如 APP_INITIALIZER、通过 fetch 加载的 JSON 或 platformBrowserDynamic),请将 strictMatching: false 设为临时的安全默认值。 有关代码示例 ,请参阅“修复”选项 - 选项 B 。
严格匹配疑难解答
症状
- API 请求在升级到 v5 后返回
@azure/msal-angular(或在 v5 次要版本(如 5.0.x → 5.1.x)之间)。 - 传出的 HTTP 请求中缺少
Authorization: Bearer <token>标头。 - 未报告生成时或运行时错误 - 失败为 无提示。
- 该问题可能只会在某些环境(例如预发布/生产)中出现,在这些环境中,API 基础 URL 与开发环境不同。
修复选项
选项 A:更新密钥以使用严格匹配(建议)
更新您的 protectedResourceMap 密钥,以使用符合严格匹配规则的精确路径或通配符。 此方法是首选方法,因为严格匹配更安全且更具可预测性:
{
interactionType: InteractionType.Redirect,
protectedResourceMap: new Map([
// Exact path — matches only this URL
["https://graph.microsoft.com/v1.0/me", ["user.read"]],
// Wildcard — matches all sub-paths of the API
["https://api.example.com/v1/*", ["api.scope"]]
])
// strictMatching defaults to true — no need to set it
}
选项 B:设置 strictMatching: false(用于动态配置的后备方案)
protectedResourceMap如果密钥在运行时动态加载(例如,来自APP_INITIALIZER、JSON 配置或platformBrowserDynamic),并且无法保证它们包含确切的路径或通配符,则设置为strictMatching: false临时安全默认值:
{
interactionType: InteractionType.Redirect,
protectedResourceMap: new Map([
[config.apiUri, config.apiScopes]
]),
// Dynamic keys may be base URLs without wildcards.
// Remove once keys are migrated to exact paths or wildcard patterns.
strictMatching: false
}
注释
为确保向后兼容性,提供了旧版匹配功能 (strictMatching: false),该功能可能会在未来的主要版本中被移除。
运行时警告
当 strictMatching 未被显式配置时,在初始化过程中,MsalInterceptor 会通过 MSAL 记录器发出一次性运行时警告。 如果看到此警告,请按照上述修复选项进行操作。
可选 authRequest
有关可在 MsalInterceptorConfiguration 中设置的可选 authRequest 的更多信息,请参阅我们的多租户文档。
从 msal-angular v1 到 v2 的变更
注释
MSAL Angular v1 的 MsalAngularConfiguration 中的 unprotectedResourceMap 已弃用,且不再有效。
-
protectedResourceMap已移至MsalInterceptorConfiguration对象,并且可以作为Map<string, Array<string|ProtectedResourceScopes>>传递。MsalAngularConfiguration已弃用,不再有效。 - 不再支持将根域放在
protectedResourceMap中以保护所有路由。 请改用通配符匹配。
有关如何配置范围的详细信息,请参阅 我们的常见问题解答。