Move samples to Entropy (#120)

This commit is contained in:
Ryan Brandenburg 2017-02-08 09:36:44 -08:00 committed by GitHub
parent aeab73f9f6
commit 829050ec31
13 changed files with 5 additions and 419 deletions

View File

@ -7,4 +7,8 @@ Travis: [![Travis](https://travis-ci.org/aspnet/Antiforgery.svg?branch=dev)](h
Antiforgery system for generating secure tokens to prevent Cross-Site Request Forgery attacks.
This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo.
This project is part of ASP.NET Core. You can find documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo.
Samples can be found in [Entropy](https://github.com/aspnet/Entropy).
The [MVC](https://github.com/aspnet/Entropy/tree/dev/samples/Antiforgery.MvcWithAuthAndAjax) sample shows how to use Antiforgery in MVC when making AJAX requests.
The [Angular](https://github.com/aspnet/Entropy/tree/dev/samples/Antiforgery.Angular1) sample shows how to use Antiforgery with Angular 1.

View File

@ -1,24 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFrameworks>net451;netcoreapp1.1</TargetFrameworks>
<RuntimeIdentifier Condition=" '$(TargetFramework)' != 'netcoreapp1.1' ">win7-x64</RuntimeIdentifier>
<OutputType>Exe</OutputType>
<NetCoreAppImplicitPackageVersion>1.2.0-*</NetCoreAppImplicitPackageVersion>
</PropertyGroup>
<ItemGroup>
<Content Update="wwwroot\**\*;web.config" CopyToPublishDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Antiforgery\Microsoft.AspNetCore.Antiforgery.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="1.2.0-*" />
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="1.2.0-*" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.2.0-*" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.2.0-*" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.2.0-*" />
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
</ItemGroup>
</Project>

View File

@ -1,81 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
namespace AntiforgerySample
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Angular's default header name for sending the XSRF token.
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
services.AddSingleton<TodoRepository>();
}
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery, IOptions<AntiforgeryOptions> options, TodoRepository repository)
{
app.Use(next => context =>
{
if (
string.Equals(context.Request.Path.Value, "/", StringComparison.OrdinalIgnoreCase) ||
string.Equals(context.Request.Path.Value, "/index.html", StringComparison.OrdinalIgnoreCase))
{
// We can send the request token as a JavaScript-readable cookie, and Angular will use it by default.
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false });
}
return next(context);
});
app.UseDefaultFiles();
app.UseStaticFiles();
app.Map("/api/items", a => a.Run(async context =>
{
if (string.Equals("GET", context.Request.Method, StringComparison.OrdinalIgnoreCase))
{
var items = repository.GetItems();
await context.Response.WriteAsync(JsonConvert.SerializeObject(items));
}
else if (string.Equals("POST", context.Request.Method, StringComparison.OrdinalIgnoreCase))
{
// This will throw if the token is invalid.
await antiforgery.ValidateRequestAsync(context);
var serializer = new JsonSerializer();
using (var reader = new JsonTextReader(new StreamReader(context.Request.Body)))
{
var item = serializer.Deserialize<TodoItem>(reader);
repository.Add(item);
}
context.Response.StatusCode = 204;
}
}));
}
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}

View File

@ -1,13 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Newtonsoft.Json;
namespace AntiforgerySample
{
public class TodoItem
{
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
}
}

View File

@ -1,31 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
namespace AntiforgerySample
{
public class TodoRepository
{
private List<TodoItem> _items;
public TodoRepository()
{
_items = new List<TodoItem>()
{
new TodoItem() { Name = "Mow the lawn" },
new TodoItem() { Name = "Do the dishes" },
};
}
public IEnumerable<TodoItem> GetItems()
{
return _items;
}
public void Add(TodoItem item)
{
_items.Add(item);
}
}
}

View File

@ -1,9 +0,0 @@
<?xml version="1.0"?>
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" />
</system.webServer>
</configuration>

View File

@ -1,47 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8" />
<title>Todo List Antiforgery Sample</title>
<link rel="stylesheet" href="//ajax.aspnetcdn.com/ajax/bootstrap/3.3.5/css/bootstrap.min.css" />
</head>
<body ng-app="TODO" ng-controller="todoController">
<div class="container">
<div class="row">
<h1>Todo List Antiforgery Sample</h1>
</div>
<div class="row">
<div class="col-lg-6">
<table class="table">
<thead>
<tr><th colspan="2">TODO List</th></tr>
</thead>
<tbody>
<tr ng-repeat="item in itemList">
<td>{{$index + 1}}</td>
<td>
{{item.name}}
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="row">
<form class="form-inline">
<div class="form-group">
<label for="name">New Item:</label>
<input type="text" class="form-control" id="name" placeholder="(Enter Todo Item)" ng-model="item.name">
</div>
<button class="btn btn-default" value="Create" ng-click="create(item)">Create</button>
</form>
</div>
</div>
<script src="//code.angularjs.org/1.4.8/angular.min.js"></script>
<script src="app.js"></script>
<script src="services.js"></script>
<script src="controllers.js"></script>
</body>
</html>

View File

@ -1,4 +0,0 @@
angular.module('TODO', [
'TODO.controllers',
'TODO.services'
]);

View File

@ -1,21 +0,0 @@
angular.module('TODO.controllers', []).
controller('todoController', function ($scope, todoApi) {
$scope.itemList = [];
$scope.item = {};
$scope.refresh = function (item) {
todoApi.getItems().success(function (response) {
$scope.itemList = response;
});
};
$scope.create = function (item) {
todoApi.create(item).success(function (response) {
$scope.item = {};
$scope.refresh();
});
};
// Load initial items
$scope.refresh();
});

View File

@ -1,22 +0,0 @@
angular.module('TODO.services', []).
factory('todoApi', function ($http) {
var todoApi = {};
todoApi.getItems = function () {
return $http({
method: 'GET',
url: '/api/items'
});
}
todoApi.create = function (item) {
return $http({
method: 'POST',
url: '/api/items',
data: item
});
};
return todoApi;
});

View File

@ -1,44 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Net.Http;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Configuration;
namespace Microsoft.AspNetCore.Antiforgery.FunctionalTests
{
public class AntiForgerySampleTestFixture : IDisposable
{
private readonly TestServer _server;
public AntiForgerySampleTestFixture()
{
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddInMemoryCollection(new[]
{
new KeyValuePair<string, string>("webroot", "wwwroot")
});
var builder = new WebHostBuilder()
.UseConfiguration(configurationBuilder.Build())
.UseStartup(typeof(AntiforgerySample.Startup));
_server = new TestServer(builder);
Client = _server.CreateClient();
Client.BaseAddress = new Uri("http://localhost");
}
public HttpClient Client { get; }
public void Dispose()
{
Client.Dispose();
_server.Dispose();
}
}
}

View File

@ -1,101 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Net.Http.Headers;
using Xunit;
namespace Microsoft.AspNetCore.Antiforgery.FunctionalTests
{
public class AntiforgerySampleTests : IClassFixture<AntiForgerySampleTestFixture>
{
public AntiforgerySampleTests(AntiForgerySampleTestFixture fixture)
{
Client = fixture.Client;
}
public HttpClient Client { get; }
[Fact]
public async Task ItemsPage_SetsXSRFTokens()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/Index.html");
// Assert
var setCookieHeaderValue = RetrieveAntiforgeryCookie(response);
Assert.NotNull(setCookieHeaderValue);
Assert.False(string.IsNullOrEmpty(setCookieHeaderValue.Value));
Assert.Null(setCookieHeaderValue.Domain);
Assert.Equal("/", setCookieHeaderValue.Path);
Assert.False(setCookieHeaderValue.Secure);
setCookieHeaderValue = RetrieveAntiforgeryToken(response);
Assert.NotNull(setCookieHeaderValue);
Assert.False(string.IsNullOrEmpty(setCookieHeaderValue.Value));
Assert.Null(setCookieHeaderValue.Domain);
Assert.Equal("/", setCookieHeaderValue.Path);
Assert.False(setCookieHeaderValue.Secure);
}
[Fact]
public async Task PostItem_NeedsHeader()
{
// Arrange
var httpResponse = await Client.GetAsync("http://localhost");
var cookie = RetrieveAntiforgeryCookie(httpResponse);
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/items");
// Act
var exception = await Assert.ThrowsAsync<AntiforgeryValidationException>(async () =>
{
var response = await Client.SendAsync(httpRequestMessage);
});
// Assert
Assert.Contains($"The required antiforgery cookie \"{cookie.Name}\" is not present.", exception.Message);
}
[Fact]
public async Task PostItem_XSRFWorks()
{
// Arrange
var httpResponse = await Client.GetAsync("/Index.html");
var cookie = RetrieveAntiforgeryCookie(httpResponse);
var token = RetrieveAntiforgeryToken(httpResponse);
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/items");
httpRequestMessage.Headers.Add("Cookie", $"{cookie.Name}={cookie.Value}");
httpRequestMessage.Headers.Add("X-XSRF-TOKEN", token.Value);
// Act
var response = await Client.SendAsync(httpRequestMessage);
// Assert
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
}
private static SetCookieHeaderValue RetrieveAntiforgeryToken(HttpResponseMessage response)
{
return response.Headers.GetValues(HeaderNames.SetCookie)
.Select(setCookieValue => SetCookieHeaderValue.Parse(setCookieValue))
.Where(setCookieHeaderValue => setCookieHeaderValue.Name == "XSRF-TOKEN")
.FirstOrDefault();
}
private static SetCookieHeaderValue RetrieveAntiforgeryCookie(HttpResponseMessage response)
{
return response.Headers.GetValues(HeaderNames.SetCookie)
.Select(setCookieValue => SetCookieHeaderValue.Parse(setCookieValue))
.Where(setCookieHeaderValue => setCookieHeaderValue.Name.StartsWith(".AspNetCore.Antiforgery."))
.FirstOrDefault();
}
}
}

View File

@ -1,21 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\build\common.props" />
<PropertyGroup>
<TargetFrameworks>netcoreapp1.1;net451</TargetFrameworks>
<RuntimeIdentifier Condition=" '$(TargetFramework)' != 'netcoreapp1.1' ">win7-x64</RuntimeIdentifier>
<SignAssembly>false</SignAssembly>
<PublicSign>false</PublicSign>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\samples\AntiforgerySample\AntiforgerySample.csproj" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-*" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0-*" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="1.2.0-*" />
<PackageReference Include="Moq" Version="4.6.36-*" />
<PackageReference Include="xunit" Version="2.2.0-*" />
</ItemGroup>
</Project>