Skip to content

Commit ced8a21

Browse files
author
Anton Wieslander
committed
Reflection
1 parent 3a28171 commit ced8a21

13 files changed

+309
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ Full Playlist can be found [here](https://www.youtube.com/playlist?list=PLOeFnOV
1212
- [Channels](https://youtu.be/E0Ld7ZgE4oY)
1313
- [MVC](https://youtu.be/u4O-b1BJg98)
1414
- [IEnumerable](https://youtu.be/at6weLnskpU)
15+
- [Reflection](https://youtu.be/cdG2JxuZvNI)

Reflection/Reflection.sln

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.30011.22
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApp", "WebApp\WebApp.csproj", "{FB323F04-C6AE-41C2-9047-934BB7C297D0}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{FB323F04-C6AE-41C2-9047-934BB7C297D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{FB323F04-C6AE-41C2-9047-934BB7C297D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{FB323F04-C6AE-41C2-9047-934BB7C297D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{FB323F04-C6AE-41C2-9047-934BB7C297D0}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {90DE1BA6-8E4D-4628-91DA-9A0665BD81EB}
24+
EndGlobalSection
25+
EndGlobal

Reflection/WebApp/AuthHandler.cs

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using Microsoft.AspNetCore.Authorization;
2+
using Microsoft.AspNetCore.Mvc;
3+
using Microsoft.AspNetCore.Mvc.Controllers;
4+
using Microsoft.AspNetCore.Routing;
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Linq;
8+
using System.Threading.Tasks;
9+
10+
namespace WebApp
11+
{
12+
public class AutoGeneratedClaim : IAuthorizationRequirement
13+
{
14+
public AutoGeneratedClaim()
15+
{}
16+
}
17+
18+
public class AuthHandler : AuthorizationHandler<AutoGeneratedClaim>
19+
{
20+
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AutoGeneratedClaim requirement)
21+
{
22+
var resource = context.Resource;
23+
if(resource is RouteEndpoint endpoint)
24+
{
25+
var metadata = endpoint.Metadata;
26+
var controllerAD = (ControllerActionDescriptor)
27+
metadata.FirstOrDefault(x => x is ControllerActionDescriptor);
28+
29+
var controller = controllerAD.ControllerTypeInfo;
30+
var action = controllerAD.MethodInfo;
31+
var targetClaim = string.Concat(controller.ToString(), ".", action.ToString().Split(" ").Last());
32+
33+
if(context.User.Claims.Any(x => x.Type.Equals(Constants.WebAppClaimType)
34+
&& x.Value.Equals(targetClaim)))
35+
{
36+
context.Succeed(requirement);
37+
return Task.CompletedTask;
38+
}
39+
}
40+
41+
context.Fail();
42+
return Task.CompletedTask;
43+
}
44+
}
45+
}

Reflection/WebApp/ClaimsService.cs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using Microsoft.AspNetCore.Authorization;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Reflection;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
9+
namespace WebApp
10+
{
11+
public class ClaimsService
12+
{
13+
public IEnumerable<string> Claims()
14+
{
15+
var authAttr = typeof(AuthorizeAttribute);
16+
var anonAttr = typeof(AllowAnonymousAttribute);
17+
18+
return typeof(Startup).Assembly.GetTypes()
19+
.Where(x => x.Name.EndsWith("Controller"))
20+
.SelectMany(x => x.GetMethods()
21+
.Where(m => m.DeclaringType.Equals(x)))
22+
.Where(x => x.GetCustomAttribute(authAttr) != null
23+
|| x.DeclaringType.GetCustomAttribute(authAttr) != null)
24+
.Where(x => x.GetCustomAttribute(anonAttr) == null)
25+
.Select(x => string.Concat(x.DeclaringType.ToString(),
26+
".", x.ToString().Split(" ").Last()));
27+
}
28+
}
29+
}

Reflection/WebApp/Constants.cs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace WebApp
2+
{
3+
public class Constants
4+
{
5+
public const string WebAppClaimType = nameof(WebAppClaimType);
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using Microsoft.AspNetCore.Authentication;
2+
using Microsoft.AspNetCore.Authorization;
3+
using Microsoft.AspNetCore.Mvc;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Security.Claims;
7+
using System.Threading.Tasks;
8+
9+
namespace WebApp.Controllers
10+
{
11+
public class HomeController : Controller
12+
{
13+
public string Index()
14+
{
15+
return "";
16+
}
17+
18+
[HttpGet]
19+
public IActionResult SignIn([FromServices] ClaimsService claimsService)
20+
{
21+
return View(claimsService.Claims());
22+
}
23+
24+
[HttpPost]
25+
public async Task<IActionResult> SignIn(IEnumerable<string> claims)
26+
{
27+
var identity = new ClaimsIdentity(claims.Select(x => new Claim(Constants.WebAppClaimType, x)), "Identity");
28+
var principal = new ClaimsPrincipal(identity);
29+
await HttpContext.SignInAsync(principal);
30+
31+
return RedirectToAction("Index");
32+
}
33+
34+
[Authorize]
35+
public string Secret()
36+
{
37+
return "";
38+
}
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using Microsoft.AspNetCore.Authorization;
2+
using Microsoft.AspNetCore.Mvc;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
9+
namespace WebApp.Controllers
10+
{
11+
[Authorize]
12+
public class ManageController : Controller
13+
{
14+
[HttpGet()]
15+
public string Secure()
16+
{
17+
return "";
18+
}
19+
20+
[HttpGet("{boi}")]
21+
public string Secure(string boi)
22+
{
23+
return "";
24+
}
25+
26+
public string Secret()
27+
{
28+
return "";
29+
}
30+
31+
[AllowAnonymous]
32+
public string Allowed()
33+
{
34+
return "";
35+
}
36+
}
37+
}

Reflection/WebApp/Program.cs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Threading.Tasks;
5+
using Microsoft.AspNetCore.Hosting;
6+
using Microsoft.Extensions.Configuration;
7+
using Microsoft.Extensions.Hosting;
8+
using Microsoft.Extensions.Logging;
9+
10+
namespace WebApp
11+
{
12+
public class Program
13+
{
14+
public static void Main(string[] args)
15+
{
16+
CreateHostBuilder(args).Build().Run();
17+
}
18+
19+
public static IHostBuilder CreateHostBuilder(string[] args) =>
20+
Host.CreateDefaultBuilder(args)
21+
.ConfigureWebHostDefaults(webBuilder =>
22+
{
23+
webBuilder.UseStartup<Startup>();
24+
});
25+
}
26+
}

Reflection/WebApp/Startup.cs

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
using Microsoft.AspNetCore.Authorization;
2+
using Microsoft.AspNetCore.Builder;
3+
using Microsoft.AspNetCore.Hosting;
4+
using Microsoft.AspNetCore.Identity;
5+
using Microsoft.Extensions.Configuration;
6+
using Microsoft.Extensions.DependencyInjection;
7+
using Microsoft.Extensions.Hosting;
8+
9+
namespace WebApp
10+
{
11+
public class Startup
12+
{
13+
public Startup(IConfiguration configuration)
14+
{
15+
Configuration = configuration;
16+
}
17+
18+
public IConfiguration Configuration { get; }
19+
20+
public void ConfigureServices(IServiceCollection services)
21+
{
22+
services.AddAuthentication("Cookie")
23+
.AddCookie("Cookie");
24+
25+
services.AddAuthorization(config =>
26+
{
27+
var policyBuilder = new AuthorizationPolicyBuilder();
28+
29+
config.DefaultPolicy = policyBuilder
30+
.AddRequirements(new AutoGeneratedClaim())
31+
.Build();
32+
});
33+
34+
services.AddScoped<IAuthorizationHandler, AuthHandler>();
35+
36+
services.AddSingleton<ClaimsService>();
37+
38+
services.AddControllersWithViews();
39+
}
40+
41+
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
42+
{
43+
if (env.IsDevelopment())
44+
{
45+
app.UseDeveloperExceptionPage();
46+
}
47+
else
48+
{
49+
app.UseExceptionHandler("/Error");
50+
51+
app.UseHsts();
52+
}
53+
54+
app.UseHttpsRedirection();
55+
app.UseStaticFiles();
56+
57+
app.UseRouting();
58+
59+
app.UseAuthentication();
60+
app.UseAuthorization();
61+
62+
app.UseEndpoints(endpoints =>
63+
{
64+
endpoints.MapDefaultControllerRoute();
65+
});
66+
}
67+
}
68+
}
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
@model IEnumerable<string>
2+
3+
4+
<form action="/Home/SignIn" method="post">
5+
6+
@foreach(var claim in Model)
7+
{
8+
<div>
9+
<label>@claim</label>
10+
<input type="checkbox" name="claims" value="@claim" />
11+
</div>
12+
}
13+
14+
<button type="submit">Sign In</button>
15+
</form>

Reflection/WebApp/WebApp.csproj

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp3.1</TargetFramework>
5+
</PropertyGroup>
6+
7+
</Project>

Reflection/WebApp/appsettings.json

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft": "Warning",
6+
"Microsoft.Hosting.Lifetime": "Information"
7+
}
8+
}
9+
}

Reflection/WebApp/wwwroot/favicon.ico

31.3 KB
Binary file not shown.

0 commit comments

Comments
 (0)