Fork me on GitHub

NetCore+Dapper WebApi架构搭建(六):添加JWT认证

WebApi必须保证安全,现在来添加JWT认证

1、打开appsettings.json添加JWT认证的配置信息

2、在项目根目录下新建一个Models文件夹,添加一个JwtSettings.cs的实体

 1 namespace Dinner.WebApi.Models
 2 {
 3     public class JwtSettings
 4     {
 5         /// <summary>
 6         /// 证书颁发者
 7         /// </summary>
 8         public string Issuer { get; set; }
 9 
10         /// <summary>
11         /// 允许使用的角色
12         /// </summary>
13         public string Audience { get; set; }
14 
15         /// <summary>
16         /// 加密字符串
17         /// </summary>
18         public string SecretKey { get; set; }
19     }
20 }
View Code

3、Startup.cs文件中的ConfigureServices添加Jwt认证的代码

 1 #region JWT认证
 2 
 3             services.Configure<JwtSettings>(Configuration.GetSection("JwtSettings"));
 4             JwtSettings setting = new JwtSettings();
 5             //绑定配置文件信息到实体
 6             Configuration.Bind("JwtSettings", setting);
 7             //添加Jwt认证
 8             services.AddAuthentication(option =>
 9             {
10                 option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
11                 option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
12             }).AddJwtBearer(config =>
13             {
14                 config.TokenValidationParameters = new TokenValidationParameters
15                 {
16                     ValidAudience = setting.Audience,
17                     ValidIssuer = setting.Issuer,
18                     IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(setting.SecretKey))
19                 };
20                 /*
21                 config.SecurityTokenValidators.Clear();
22                 config.SecurityTokenValidators.Add(new MyTokenValidate());
23                 config.Events = new JwtBearerEvents()
24                 {
25                     OnMessageReceived = context =>
26                     {
27                         var token = context.Request.Headers["myToken"];
28                         context.Token = token.FirstOrDefault();
29                         return Task.CompletedTask;
30                     }
31                 };
32                 */
33             });
34 
35             #endregion
View Code

4、Startup.cs文件中的Configure添加Jwt认证的代码

1 app.UseAuthentication();
View Code

5、基本配置都弄完了,现在是生成JwtToken,在ValuesController中添加一个生成Jwt的Action

 1 using Dinner.WebApi.Models;
 2 using Microsoft.AspNetCore.Mvc;
 3 using Microsoft.Extensions.Options;
 4 using Microsoft.IdentityModel.Tokens;
 5 using System;
 6 using System.Collections.Generic;
 7 using System.IdentityModel.Tokens.Jwt;
 8 using System.Security.Claims;
 9 using System.Text;
10 
11 namespace Dinner.WebApi.Controllers
12 {
13     [Route("api/[controller]/[action]")]
14     public class ValuesController : Controller
15     {
16         private readonly JwtSettings setting;
17         public ValuesController(IOptions<JwtSettings> _setting)
18         {
19             setting = _setting.Value;
20         }
21         // GET api/values
22         [HttpGet]
23         public IEnumerable<string> Get()
24         {
25             return new string[] { "value1", "value2" };
26         }
27 
28         // GET api/values/5
29         [HttpGet("{id}")]
30         public string Get(int id)
31         {
32             return "value";
33         }
34 
35         // POST api/values
36         [HttpPost]
37         public void Post([FromBody]string value)
38         {
39         }
40 
41         // PUT api/values/5
42         [HttpPut("{id}")]
43         public void Put(int id, [FromBody]string value)
44         {
45         }
46 
47         // DELETE api/values/5
48         [HttpDelete("{id}")]
49         public void Delete(int id)
50         {
51         }
52 
53         [HttpGet]
54         public IActionResult GetGenerateJWT()
55         {
56             try
57             {
58                 var claims = new Claim[] 
59                 {
60                     new Claim(ClaimTypes.Name, "wangshibang"),
61                     new Claim(ClaimTypes.Role, "admin, Manage")
62                 };
63                 var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(setting.SecretKey));
64                 var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
65                 var token = new JwtSecurityToken(
66                     setting.Issuer,
67                     setting.Audience,
68                     claims,
69                     DateTime.Now,
70                     DateTime.Now.AddMinutes(30),
71                     creds);
72                 return Ok(new { Token = new JwtSecurityTokenHandler().WriteToken(token) });
73             }
74             catch (Exception ex)
75             {
76                 return BadRequest(ex.Message);
77             }   
78             
79         }
80     }
81 }
View Code

这样调用这个方法就会生成一个JwtToken,然后在UsersController上面添加一个[Authorize]的特性

上一篇我们说过SwaggerUI配置的最后一句有一个options.OperationFilter<HttpHeaderOperation>(); 这里我们来看这个HttpHeaderOperation

 1 using Microsoft.AspNetCore.Authorization;
 2 using Swashbuckle.AspNetCore.Swagger;
 3 using Swashbuckle.AspNetCore.SwaggerGen;
 4 using System.Collections.Generic;
 5 using System.Linq;
 6 
 7 namespace Dinner.WebApi
 8 {
 9     public class HttpHeaderOperation : IOperationFilter
10     {
11         public void Apply(Operation operation, OperationFilterContext context)
12         {
13             if (operation.Parameters == null)
14             {
15                 operation.Parameters = new List<IParameter>();
16             }
17 
18             var actionAttrs = context.ApiDescription.ActionAttributes();
19 
20             var isAuthorized = actionAttrs.Any(a => a.GetType() == typeof(AuthorizeAttribute));
21 
22             if (isAuthorized == false) //提供action都没有权限特性标记,检查控制器有没有
23             {
24                 var controllerAttrs = context.ApiDescription.ControllerAttributes();
25 
26                 isAuthorized = controllerAttrs.Any(a => a.GetType() == typeof(AuthorizeAttribute));
27             }
28 
29             var isAllowAnonymous = actionAttrs.Any(a => a.GetType() == typeof(AllowAnonymousAttribute));
30 
31             if (isAuthorized && isAllowAnonymous == false)
32             {
33                 operation.Parameters.Add(new NonBodyParameter()
34                 {
35                     Name = "Authorization",  //添加Authorization头部参数
36                     In = "header",
37                     Type = "string",
38                     Required = false
39                 });
40             }
41         }
42     }
43 }
View Code

这个代码主要就是在swagger页面添加了一个Authorization的头部输入框信息,以便来进行验证

现在我们基本工作都做好了,打开页面测试吧,注意:传入的Authorization参数必须是Bearer xxxxxxx的形式(xxxxxxx为生成的Token)

他返回了Http200就是成功了

整个项目的框架基本算是搭建好了,这只是一个雏形而已,其实Authorize这一块需要建一个BaseController继承Controller再在BaseController上添加一个Authorize然后所有Controller继承BaseController就不用一个一个的写Authorize了,不需要验证的加个AllowAnonymous就可以了,其他的直接扩展仓储接口写仓储就可以直接调用了

源码地址: https://github.com/wangyulong0505/Dinner

posted @ 2018-04-27 14:10  雪山玉龙  阅读(2114)  评论(4编辑  收藏  举报