Compare commits

2 Commits
v2.1 ... master

Author SHA1 Message Date
fulexable
fc2f65d8e0 Commit uncommitted local changes before Gitea archival 2026-07-03 05:23:34 +09:00
jwatmore
c662aaa146 updated to ASP.NET Core 2.2 2019-01-07 21:22:19 -08:00
14 changed files with 363 additions and 369 deletions

90
.gitignore vendored
View File

@@ -1,46 +1,46 @@
# Logs # Logs
logs logs
*.log *.log
npm-debug.log* npm-debug.log*
# Runtime data # Runtime data
pids pids
*.pid *.pid
*.seed *.seed
# Directory for instrumented libs generated by jscoverage/JSCover # Directory for instrumented libs generated by jscoverage/JSCover
lib-cov lib-cov
# Coverage directory used by tools like istanbul # Coverage directory used by tools like istanbul
coverage coverage
# nyc test coverage # nyc test coverage
.nyc_output .nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt .grunt
# node-waf configuration # node-waf configuration
.lock-wscript .lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html) # Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release build/Release
# Dependency directories # Dependency directories
node_modules node_modules
jspm_packages jspm_packages
typings typings
# Optional npm cache directory # Optional npm cache directory
.npm .npm
# Optional REPL history # Optional REPL history
.node_repl_history .node_repl_history
# Generated files # Generated files
client/app/**/*.js client/app/**/*.js
client/app/**/*.js.map client/app/**/*.js.map
# .NET compiled files # .NET compiled files
bin bin
obj obj

62
.vscode/launch.json vendored
View File

@@ -1,32 +1,32 @@
{ {
// Use IntelliSense to find out which attributes exist for C# debugging // Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes // Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": ".NET Core Launch (web)", "name": ".NET Core Launch (web)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path. // If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceRoot}/bin/Debug/netcoreapp2.1/WebApi.dll", "program": "${workspaceRoot}/bin/Debug/netcoreapp2.2/WebApi.dll",
"args": [], "args": [],
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"stopAtEntry": false, "stopAtEntry": false,
"internalConsoleOptions": "openOnSessionStart", "internalConsoleOptions": "openOnSessionStart",
"env": { "env": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
}, },
"sourceFileMap": { "sourceFileMap": {
"/Views": "${workspaceRoot}/Views" "/Views": "${workspaceRoot}/Views"
} }
}, },
{ {
"name": ".NET Core Attach", "name": ".NET Core Attach",
"type": "coreclr", "type": "coreclr",
"request": "attach", "request": "attach",
"processId": "${command:pickProcess}" "processId": "${command:pickProcess}"
} }
] ]
} }

30
.vscode/tasks.json vendored
View File

@@ -1,16 +1,16 @@
{ {
"version": "0.1.0", "version": "2.0.0",
"command": "dotnet", "command": "dotnet",
"isShellCommand": true, "type": "shell",
"args": [], "args": [],
"tasks": [ "tasks": [
{ {
"taskName": "build", "label": "build",
"args": [ "args": [
"${workspaceRoot}/WebApi.csproj" "${workspaceRoot}/WebApi.csproj"
], ],
"isBuildCommand": true, "group": "build",
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
} }
] ]
} }

View File

@@ -1,39 +1,39 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using WebApi.Services; using WebApi.Services;
using WebApi.Entities; using WebApi.Entities;
namespace WebApi.Controllers namespace WebApi.Controllers
{ {
[Authorize] [Authorize]
[ApiController] [ApiController]
[Route("[controller]")] [Route("[controller]")]
public class UsersController : ControllerBase public class UsersController : ControllerBase
{ {
private IUserService _userService; private IUserService _userService;
public UsersController(IUserService userService) public UsersController(IUserService userService)
{ {
_userService = userService; _userService = userService;
} }
[AllowAnonymous] [AllowAnonymous]
[HttpPost("authenticate")] [HttpPost("authenticate")]
public IActionResult Authenticate([FromBody]User userParam) public IActionResult Authenticate([FromBody]User userParam)
{ {
var user = _userService.Authenticate(userParam.Username, userParam.Password); var user = _userService.Authenticate(userParam.Username, userParam.Password);
if (user == null) if (user == null)
return BadRequest(new { message = "Username or password is incorrect" }); return BadRequest(new { message = "Username or password is incorrect" });
return Ok(user); return Ok(user);
} }
[HttpGet] [HttpGet]
public IActionResult GetAll() public IActionResult GetAll()
{ {
var users = _userService.GetAll(); var users = _userService.GetAll();
return Ok(users); return Ok(users);
} }
} }
} }

View File

@@ -1,12 +1,12 @@
namespace WebApi.Entities namespace WebApi.Entities
{ {
public class User public class User
{ {
public int Id { get; set; } public int Id { get; set; }
public string FirstName { get; set; } public string FirstName { get; set; }
public string LastName { get; set; } public string LastName { get; set; }
public string Username { get; set; } public string Username { get; set; }
public string Password { get; set; } public string Password { get; set; }
public string Token { get; set; } public string Token { get; set; }
} }
} }

View File

@@ -1,7 +1,7 @@
namespace WebApi.Helpers namespace WebApi.Helpers
{ {
public class AppSettings public class AppSettings
{ {
public string Secret { get; set; } public string Secret { get; set; }
} }
} }

42
LICENSE
View File

@@ -1,21 +1,21 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2018 Jason Watmore Copyright (c) 2018 Jason Watmore
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.

View File

@@ -1,20 +1,20 @@
using System.IO; using System.IO;
using Microsoft.AspNetCore; using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
namespace WebApi namespace WebApi
{ {
public class Program public class Program
{ {
public static void Main(string[] args) public static void Main(string[] args)
{ {
BuildWebHost(args).Run(); BuildWebHost(args).Run();
} }
public static IWebHost BuildWebHost(string[] args) => public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args) WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>() .UseStartup<Startup>()
.UseUrls("http://localhost:4000") .UseUrls("http://localhost:4000")
.Build(); .Build();
} }
} }

View File

@@ -1,5 +1,5 @@
# aspnet-core-jwt-authentication-api # aspnet-core-jwt-authentication-api
ASP.NET Core 2.1 - JWT Authentication API ASP.NET Core 2.2 - JWT Authentication API
For documentation and instructions check out http://jasonwatmore.com/post/2018/08/14/aspnet-core-21-jwt-authentication-tutorial-with-example-api For documentation and instructions check out http://jasonwatmore.com/post/2018/08/14/aspnet-core-21-jwt-authentication-tutorial-with-example-api

View File

@@ -1,73 +1,73 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt; using System.IdentityModel.Tokens.Jwt;
using System.Linq; using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using System.Text; using System.Text;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using WebApi.Entities; using WebApi.Entities;
using WebApi.Helpers; using WebApi.Helpers;
namespace WebApi.Services namespace WebApi.Services
{ {
public interface IUserService public interface IUserService
{ {
User Authenticate(string username, string password); User Authenticate(string username, string password);
IEnumerable<User> GetAll(); IEnumerable<User> GetAll();
} }
public class UserService : IUserService public class UserService : IUserService
{ {
// users hardcoded for simplicity, store in a db with hashed passwords in production applications // users hardcoded for simplicity, store in a db with hashed passwords in production applications
private List<User> _users = new List<User> private List<User> _users = new List<User>
{ {
new User { Id = 1, FirstName = "Test", LastName = "User", Username = "test", Password = "test" } new User { Id = 1, FirstName = "Test", LastName = "User", Username = "test", Password = "test" }
}; };
private readonly AppSettings _appSettings; private readonly AppSettings _appSettings;
public UserService(IOptions<AppSettings> appSettings) public UserService(IOptions<AppSettings> appSettings)
{ {
_appSettings = appSettings.Value; _appSettings = appSettings.Value;
} }
public User Authenticate(string username, string password) public User Authenticate(string username, string password)
{ {
var user = _users.SingleOrDefault(x => x.Username == username && x.Password == password); var user = _users.SingleOrDefault(x => x.Username == username && x.Password == password);
// return null if user not found // return null if user not found
if (user == null) if (user == null)
return null; return null;
// authentication successful so generate jwt token // authentication successful so generate jwt token
var tokenHandler = new JwtSecurityTokenHandler(); var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret); var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
var tokenDescriptor = new SecurityTokenDescriptor var tokenDescriptor = new SecurityTokenDescriptor
{ {
Subject = new ClaimsIdentity(new Claim[] Subject = new ClaimsIdentity(new Claim[]
{ {
new Claim(ClaimTypes.Name, user.Id.ToString()) new Claim(ClaimTypes.Name, user.Id.ToString())
}), }),
Expires = DateTime.UtcNow.AddDays(7), Expires = DateTime.UtcNow.AddDays(7),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
}; };
var token = tokenHandler.CreateToken(tokenDescriptor); var token = tokenHandler.CreateToken(tokenDescriptor);
user.Token = tokenHandler.WriteToken(token); user.Token = tokenHandler.WriteToken(token);
// remove password before returning // remove password before returning
user.Password = null; user.Password = null;
return user; return user;
} }
public IEnumerable<User> GetAll() public IEnumerable<User> GetAll()
{ {
// return users without passwords // return users without passwords
return _users.Select(x => { return _users.Select(x => {
x.Password = null; x.Password = null;
return x; return x;
}); });
} }
} }
} }

View File

@@ -1,76 +1,72 @@
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using WebApi.Helpers;
using WebApi.Helpers; using WebApi.Services;
using WebApi.Services; using Microsoft.IdentityModel.Tokens;
using Microsoft.IdentityModel.Tokens; using System.Text;
using System.Text; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Mvc;
namespace WebApi namespace WebApi
{ {
public class Startup public class Startup
{ {
public Startup(IConfiguration configuration) public Startup(IConfiguration configuration)
{ {
Configuration = configuration; Configuration = configuration;
} }
public IConfiguration Configuration { get; } public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container. // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
services.AddCors(); services.AddCors();
services.AddMvc(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
// configure strongly typed settings objects // configure strongly typed settings objects
var appSettingsSection = Configuration.GetSection("AppSettings"); var appSettingsSection = Configuration.GetSection("AppSettings");
services.Configure<AppSettings>(appSettingsSection); services.Configure<AppSettings>(appSettingsSection);
// configure jwt authentication // configure jwt authentication
var appSettings = appSettingsSection.Get<AppSettings>(); var appSettings = appSettingsSection.Get<AppSettings>();
var key = Encoding.ASCII.GetBytes(appSettings.Secret); var key = Encoding.ASCII.GetBytes(appSettings.Secret);
services.AddAuthentication(x => services.AddAuthentication(x =>
{ {
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}) })
.AddJwtBearer(x => .AddJwtBearer(x =>
{ {
x.RequireHttpsMetadata = false; x.RequireHttpsMetadata = false;
x.SaveToken = true; x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters x.TokenValidationParameters = new TokenValidationParameters
{ {
ValidateIssuerSigningKey = true, ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key), IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false, ValidateIssuer = false,
ValidateAudience = false ValidateAudience = false
}; };
}); });
// configure DI for application services // configure DI for application services
services.AddScoped<IUserService, UserService>(); services.AddScoped<IUserService, UserService>();
} }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{ {
loggerFactory.AddConsole(Configuration.GetSection("Logging")); // global cors policy
loggerFactory.AddDebug(); app.UseCors(x => x
.AllowAnyOrigin()
// global cors policy .AllowAnyMethod()
app.UseCors(x => x .AllowAnyHeader());
.AllowAnyOrigin()
.AllowAnyMethod() app.UseAuthentication();
.AllowAnyHeader()
.AllowCredentials()); app.UseMvc();
}
app.UseAuthentication(); }
}
app.UseMvc();
}
}
}

View File

@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" /> <PackageReference Include="Microsoft.AspNetCore.App" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,10 +1,9 @@
{ {
"Logging": { "Logging": {
"IncludeScopes": false, "LogLevel": {
"LogLevel": { "Default": "Debug",
"Default": "Debug", "System": "Information",
"System": "Information", "Microsoft": "Information"
"Microsoft": "Information" }
} }
} }
}

View File

@@ -1,11 +1,10 @@
{ {
"AppSettings": { "AppSettings": {
"Secret": "THIS IS USED TO SIGN AND VERIFY JWT TOKENS, REPLACE IT WITH YOUR OWN SECRET, IT CAN BE ANY STRING" "Secret": "sdfsdf"
}, },
"Logging": { "Logging": {
"IncludeScopes": false, "LogLevel": {
"LogLevel": { "Default": "Warning"
"Default": "Warning" }
} }
} }
}