ton*_*one 5 antiforgerytoken asp.net-identity asp.net-core angular
我目前正在尝试使安全性与新发布的Asp.Net Core 2.0上的Angular 4(4.3.5)配合使用,尤其是防伪令牌。
我正在使用JavascriptServices,它提供了入门应用程序(它是Visual Studio 2017.3中的默认Angular模板)。Javascript服务在.cshtml页面上托管Angular站点的主页。实际上,这确实是非常有益的,因为我可以使用标准表单身份验证(点网核心身份)将所有内容锁定下来,当用户不在时,将用户重定向到/ Account / Login上的单独(非Angular)登录页面。登录。然后您可以登录该页面并重定向到主页,然后在授权用户的上下文中启动并运行该spa。
该工作应用程序可以在这里找到。
最后一个难题是使ValidateAntiForgeryToken属性正常工作。当您登录到“帐户/登录”页面时,这很好,因为它不是在angular 4的上下文中运行。但是,当我在主页的Angular 4中运行时,当我向服务器发帖时,如果该属性存在,则该帖子将被ValidateAntiForgeryToken阻止。
因此,我已在Account / Logout方法上注释了ValidateAntiForgeryToken属性。这是因为我正在使用Angular http帖子从站点注销。在不使用该属性时可以使用,但是在使用该属性时会失败/被阻止。
继角4机制的文档,发现在这里,我已经改变了反伪造令牌名称以匹配角4识别。为此,我修改了Startup.cs文件,并添加了以下几行:
public void ConfigureServices(IServiceCollection services)
{
services.AddAntiforgery(options =>
{
options.Cookie.Name = "XSRF-TOKEN";
options.Cookie.HttpOnly = false;
});
...
}
Run Code Online (Sandbox Code Playgroud)
这应该使Angular应用程序能够使用Angular 4期望的名称访问Anti Forgery cookie。
在我的应用程序中,我刚刚转换为使用新的HttpClient服务(显然,不推荐使用Http服务!)应该使用拦截器将XSRF_TOKEN自动发送到服务器。
但是我一直无法完成这项工作。
我尝试使用HttpClient服务进行标准的帖子通话:
this.httpClient.post(this.baseUrl + 'Account/Logout', "", options).subscribe(result => {
location.replace("/");
}, error => {
console.error(error);
})
Run Code Online (Sandbox Code Playgroud)
我尝试手动添加标题:
let token = this.cookieService.get("XSRF-TOKEN");
console.log(token);
var httpHeaders = new HttpHeaders({ 'XSRF-TOKEN': token })
this.httpClient.post(this.baseUrl + 'Account/Logout', "", { headers: httpHeaders }).subscribe(result => {
location.replace("/");
}, error => {
console.error(error);
})
Run Code Online (Sandbox Code Playgroud)
我尝试使用带有和不带有标题的旧服务:
let token = this.cookieService.get("XSRF-TOKEN");
console.log(token);
let headers = new Headers({
//'Content-Type': 'application/json',
'X-XSRF-TOKEN': token
});
let options = new RequestOptions({ headers: headers });
this.http.post(this.baseUrl + 'Account/Logout', "", options).subscribe(result => {
location.replace("/")
}, error => console.error(error));
Run Code Online (Sandbox Code Playgroud)
不幸的是,我没有运气。还有其他人设法使它正常工作吗?
好的,我已经找到解决方案了。
我的 Index.cshtml 页面现在如下所示:
@Html.AntiForgeryToken()
<app>Loading...</app>
<script src="~/dist/vendor.js" asp-append-version="true"></script>
@section scripts {
<script src="~/dist/main-client.js" asp-append-version="true"></script>
}
Run Code Online (Sandbox Code Playgroud)
其作用是在服务器端生成防伪令牌,并将其放置在页面上的隐藏输入字段中。当您查看页面源代码时,隐藏的输入字段如下所示:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8DaEnvKVNL9EhPVzHKQWhC-PeT4eNm_svdTEyGZje4WnH34sBfG_D_AphtPzBM1JEkQUHsSX1KWBivxAOtPsOvfMKs5N_dLn0Sr3xRG-N2s0oFaa3-yvG87qdzXYm1yBSYH7dlRiBu5It3wi2iYzWqyo4B1i_iRtmikz41gmuldze8VE72zVqmeHZav5rQiHkw" />
Run Code Online (Sandbox Code Playgroud)
在我的 Logout 方法中,我获取令牌并将其在标头中提交到服务器端控制器。标头名称为 RequestVerificationToken,不需要下划线。
Logout() {
let token: any = $("input[name=__RequestVerificationToken]").val();
if (token !== null) {
var httpHeaders: any = new HttpHeaders({ 'RequestVerificationToken': token });
this.httpClient.post("/Account/Logout", null, { headers: httpHeaders }).subscribe(() => {
window.location.replace("/Account/Login");
}, error => {
console.log(error);
});
}
}
Run Code Online (Sandbox Code Playgroud)
在服务器端,AntiForgery 过滤器运行,将其与提交的值进行比较,如果是预期的值,将允许执行服务器端的 Account/Logout 方法。
服务器端方法如下所示:
//
// POST: /Account/Logout
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Logout()
{
await _signInManager.SignOutAsync();
return RedirectToAction(nameof(HomeController.Index), "Home");
}
Run Code Online (Sandbox Code Playgroud)
在Logout方法中放置一个断点将证明它执行了。
这里可能有一个陷阱。我不确定令牌是否会在每个请求时发生变化。我没有对此做过任何测试。如果是这样,则需要在每次请求后将新令牌添加到页面。
另外,我不需要修改默认 cookie 的行为。我不是用 Angular 4 的方式来做这件事。它纯粹是 ASP.Net 方法。即在Startup.cs文件中的ConfigureServices方法中,我已经注释掉了Cookie的更改:
public void ConfigureServices(IServiceCollection services)
{
//services.AddAntiforgery(options =>
//{
// options.Cookie.Name = "XSRF-TOKEN";
// options.Cookie.HttpOnly = false;
//});
Run Code Online (Sandbox Code Playgroud)
如果您认为您已经找到了更好的方法,请务必发布您的解决方案。
| 归档时间: |
|
| 查看次数: |
4369 次 |
| 最近记录: |