.Net 5框架下的Web API+JWT or Identtityservice4
目录
1.Rest_Full风格
2. wep api Swageer
3.cmd命令程序开启web程序
4.api 前后端调用例子
5.浏览器跨域,同源策略
6.请求压缩响应结果
7.鉴权中心
8. JWT验证流程思路
1.Rest_Full风格:不再是调用方法,把服务资源化(所有东西视为资源)看做一个整体,对外提供URL-统一资源定位器 提供Get/Post/Delete/Update
2..Net5 默认自带Swageer 注意,statup中间件注册没生效可能会存在顺序关系!
3.cmd命令程序开启web程序
再vs里面右键项目程序-打开程序所在的文件夹 在当前目录输入cmd进入命令程序
输入命令 dotnet run --urls=“http://*:5400”
4.api 前后端调用例子
namespace Zhaoxi.AspNetCoreDemo.WebApi.Controllers { /// <summary> /// 特性路由 /// template:中括号代表 变量 /// 控制器上标的Route模板和Action上标记Route模板内容会链接起来 /// 如果加上特性路由以后:确定到方法了,以路由定义的名称为准 /// </summary> //[Route("api/[controller]")] //[CustomActionFilterAttribute]//整个控制器都支持跨域了; [ApiExplorerSettings(GroupName = "V1")] [ApiController] //WebApi特有 public class FirstController : ControllerBase { [HttpGet] [Route("api/[controller]/GetDataTable")] public DataTable GetDataTable() { return null; } /// <summary> /// 这是V1版本的GetString /// </summary> /// <returns></returns> [HttpGet] [Route("api/[controller]/GetString")] public string GetToString() { //HttpContext.Response.Headers.Add("Access-Control-Allow-Origin","*");//允许跨域了; var reuslt = Newtonsoft.Json.JsonConvert.SerializeObject(new { Id = 123, Name = "闪电五连鞭" }); Console.WriteLine(reuslt); return reuslt; } /// <summary> /// 这是V1版本的GetString002 /// </summary> /// <returns></returns> [HttpGet] [Route("api/[controller]/GetString002")] public string GetString002() { //HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");//允许跨域了; return Newtonsoft.Json.JsonConvert.SerializeObject(new { Id = 123, Name = "闪电五连鞭" }); } /// <summary> /// 这是V1版本的Add /// </summary> /// <returns>name</returns> [HttpPost] [Route("api/[controller]/Add/{name:required}")] public string Add(string name) { //HttpContext.Response.Headers.Add("Access-Control-Allow-Origin","*");//允许跨域了; return Newtonsoft.Json.JsonConvert.SerializeObject(new { Id = 234, Name = name }); } [HttpPut] [Route("api/[controller]/Update/{id:int}")] public int Update(int Id) { return Id; } [Route("api/[controller]/Update/{id:int}")] [HttpDelete] public int Delete(int Id) { return Id; } [Route("api/[controller]/Patch")] [HttpPatch] public int Patch() { return 123; } [Route("api/[controller]/GetUser")] [HttpPost] public string GetUser(Users user) { Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(user)); return Newtonsoft.Json.JsonConvert.SerializeObject(user); } [Route("api/[controller]/GetStudent")] [HttpGet] public string GetStudent() { return Newtonsoft.Json.JsonConvert.SerializeObject(new { id = 234, Name = "笑脸", Age = 24, Description = "奥术大师多" }); } } }
@{ ViewData["Title"] = "Index"; } <h1>this is Client Api</h1> <form method="post" action="/api/Ninth/register?id=1"> <div class="row"> <div class="col-md-5"> <h2>Test </h2> <p> <input type="text" id="txtAccount" name="账号" /> <input type="text" id="txtPassword" name="密码" /> <input type="button" id="btnLogin" value="登陆" /> </p> <p><input type="text" id="txtId" name="id" /> </p> <p> <input type="button" id="btnGet1" value="Get1" /> <input type="button" id="btnGet2" value="Get2" /> <input type="button" id="btnGet3" value="Get3" /> <input type="button" id="btnGet4" value="Get4" /> </p> <p> <input type="button" id="btnGet5" value="Get5" /> <input type="button" id="btnGet6" value="Get6" /> <input type="button" id="btnGet7" value="Get7" /> </p> <p> <input type="button" id="btnPost1" value="Post1" /> <input type="button" id="btnPost2" value="Post2" /> <input type="button" id="btnPost3" value="Post3" /> <input type="button" id="btnPost4" value="Post4" /> </p> @*<p><input type="submit" id="btnPost" /> </p>*@ <p> <input type="button" id="btnPut1" value="Put1" /> <input type="button" id="btnPut2" value="Put2" /> <input type="button" id="btnPut3" value="Put3" /> <input type="button" id="btnPut4" value="Put4" /> @*<input type="button" id="btnPut5" value="Put5" /> <input type="button" id="btnPut6" value="Put6" />*@ </p> <p> <input type="button" id="httpGet" value="后台模拟HttpGet请求" /> <input type="button" id="httpPost" value="后台模拟HttpPost请求" /> </p> <p> <input type="button" id="btnGetCors1" value="跨域Get1" /> </p> </div> </div> <script src="~/lib/jquery/dist/jquery.min.js"></script> <script> $(function () { var user = { UserID: "11", UserName: "Richard", UserEmail: "1030499676@qq.com" }; var info = "this is muti model"; $("#btnGet1").on("click", function () { //$.ajax({ url: "/api/Ninth", type: "get", data: { "userName": "Superman" }, success: function (data) { alert(JSON.stringify(data)); }, datatype: "json" });//指向接口,参数匹配的,大小写不区分 $.ajax({ //url: "/api/Ninth/GetUserByName?ticket=" + ticket url: "/api/Ninth/GetUserByName", type: "get", data: { "username": "Superman" }, //beforeSend: function (XHR) { // //发送ajax请求之前向http的head里面加入验证信息 // XHR.setRequestHeader('Authorization', 'BasicAuth ' + ticket); //}, success: function (data) { alert(JSON.stringify(data)); }, datatype: "json" }); }); $("#btnGet2").on("click", function () {//单个参数 $.ajax({ url: "/api/Ninth/GetUserByID", type: "get", data: { "id": $("#txtId").val() }, success: function (data) { alert(JSON.stringify(data)); }, datatype: "json" }); }); $("#btnGet3").on("click", function () {//两个参数 $.ajax({ url: "/api/Ninth/GetUserByNameId", type: "get", data: { "userName": "Superman", "id": $("#txtId").val() }, success: function (data) { alert(JSON.stringify(data)); }, datatype: "json" }); }); $("#btnGet4").on("click", function () {//无参数 $.ajax({ url: "/api/Ninth/Get", type: "get", data: "", success: function (data) { alert(JSON.stringify(data)); }, datatype: "json" }); }); $("#btnGet5").on("click", function () {//传递实体,序列化后传递 $.ajax({ url: "/api/Ninth/GetUserByModelSerialize", type: "get", data: { userString: JSON.stringify(user) }, success: function (data) { alert(JSON.stringify(data)); }, datatype: "json" }); }); //只能传递JSON字符串、[frombody] [fromuri] [fromform]---现在不行 $("#btnGet6").on("click", function () {//传递实体,序列化后传递 $.ajax({ url: "/api/Ninth/GetUserByModelSerializeWithoutGet", type: "get", data: { userString: JSON.stringify(user) }, success: function (data) { alert(JSON.stringify(data)); }, datatype: "json" }); }); $("#btnGet7").on("click", function () {//传递实体,序列化后传递 405 Method Not Allowed 不带httpget需要用get开头 $.ajax({ url: "/api/Ninth/NoGetUserByModelSerializeWithoutGet", type: "get", data: { userString: JSON.stringify(user) }, success: function (data) { alert(JSON.stringify(data)); }, datatype: "json" }); }); $("#btnPost1").on("click", function () {//单个值传递,json数据不要key,这样后台才能获取 $.ajax({ url: "/api/Ninth/RegisterNone", type: "post", data: {}, success: function (data) { alert(JSON.stringify(data)); }, datatype: "json" }); }); $("#btnPost2").on("click", function () {//key-value形式后台拿不到这个参数,但是可以直接访问 $.ajax({ url: "/api/Ninth/Register", type: "post", data: { "id": $("#txtId").val() }, success: function (data) { alert(JSON.stringify(data)); }, datatype: "json" }); }); $("#btnPost3").on("click", function () {//传递json格式的,后台可以用实体接收 $.ajax({ url: "/api/Ninth/RegisterUser", type: "post", data: user, success: function (data) { alert(JSON.stringify(data)); }, datatype: "json" }); }); $("#btnPost4").on("click", function () {//传递json序列化后的格式 $.ajax({ url: "/api/Ninth/RegisterUser", type: "post", data: JSON.stringify(user), success: function (data) { alert(JSON.stringify(data)); }, datatype: "json", contentType: 'application/json', }); }); //也可以还是包装成一个对象 $("#btnPut1").on("click", function () {//单个值传递,json数据不要key,这样后台才能获取 $.ajax({ url: "/api/Ninth/RegisterNoKeyPut", type: "put", data: { "": $("#txtId").val() }, success: function (data) { alert(JSON.stringify(data)); }, datatype: "json" }); }); $("#btnPut2").on("click", function () {//key-value形式后台拿不到 $.ajax({ url: "/api/Ninth/RegisterPut", type: "put", data: { "id": $("#txtId").val() }, success: function (data) { alert(JSON.stringify(data)); }, datatype: "json" }); }); $("#btnPut3").on("click", function () {//传递json格式的,后台可以用实体接收 $.ajax({ url: "/api/Ninth/RegisterUserPut", type: "put", data: user, success: function (data) { alert(JSON.stringify(data)); }, datatype: "json" }); }); $("#btnPut4").on("click", function () {//传递json序列化后的格式,后台可以用实体接收,需要指定contentType $.ajax({ url: "/api/Ninth/RegisterUserPut", type: "put", data: JSON.stringify(user), success: function (data) { alert(JSON.stringify(data)); }, datatype: "json", contentType: 'application/json', }); }); $("#httpGet").on("click", function () { //先请求到后台,然后由后台发送HttpGet请求再请求到第三方WebApi $.ajax({ url: "SendHttpGet", type: "get", data: {}, success: function (data) { alert(JSON.stringify(data)); }, datatype: "json", contentType: 'application/json', }); }); $("#httpPost").on("click", function () { //先请求到后台,然后由后台发送HttpPost请求再请求到第三方WebApi $.ajax({ url: "SendHttpPost", type: "post", data: {}, success: function (data) { alert(JSON.stringify(data)); }, datatype: "json", contentType: 'application/json', }); }); //$("#btnPut5").on("click", function () {//JObject接收 // $.ajax({ url: "/api/Ninth/RegisterObjectPut", type: "put", data: { "User": user, "Info": info }, success: function (data) { alert(JSON.stringify(data)); }, datatype: "json" }); //}); //$("#btnPut6").on("click", function () {//Dynamic 失败了 // $.ajax({ url: "/api/Ninth/RegisterObjectDynamicPut", type: "put", data: { "User": user, "Info": info }, success: function (data) { alert(JSON.stringify(data)); }, datatype: "json", contentType: 'application/json' }); //}); //delete一样 type换成delete //如果大家还有别的传递和获取 自动绑定好的方式,欢迎分享 $("#btnLogin").on("click", function () { $.ajax({ url: "/api/Ninth/Login", type: "GET", data: { "Account": $("#txtAccount").val(), "Password": $("#txtPassword").val() }, success: function (data) { var result = JSON.parse(data); if (result.Result) { ticket = result.Ticket; alert(result.Ticket); } else { alert("failed"); } }, datatype: "json" }); }); var ticket = "";//登陆后放在某个html里面,ajax都得带上 jQuery.support.cors = true; var location = "https://localhost:5400/api/first/GetString"; $("#btnGetCors1").on("click", function () { $.ajax({ url: location, type: "get", data: { "id": 1 }, success: function (data) { alert(JSON.stringify(data)); }, datatype: "json" }); }); }); </script> </form>
5.浏览器跨域,同源策略
正常:正常http请求是通过浏览器发送给服务器 服务器知道请求人的http协议的信息,如:端口,ip
跨域:ajax http请求是直接一个链接请求到服务器,服务器不知道请求人的身份。
如果没有同源策略.存储在服务器的cookie session 谁过来都能读取
经典的跨域请求错误事例:
多种跨域策略之一
服务器设置全局允许跨域请求 statup.cs.configure():或者使用特性,控制某个控制器允许跨域
多种跨域策略之一 在statup.cs.ConfigureServices()下面
多种跨域策略之二, 在statup.cs.Configure()下面
app.UseCors("AllowCors"); //必须要在UseRouting 之后 在 UseAuthorization之前
6.请求压缩响应结果
添加程序集:
在statup.cs下添加代码 支持GZip压缩格式,或者同事支持两种
在statup.cs.Configure()下面
浏览器支持的压缩方式
7.鉴权中心
Token检验流程
8. JWT验证流程思路
1.用户访问鉴权中心,鉴权返回用户token 2.用户带着token 访问api api得到用于的token 并不去AuthorizetionServer鉴权中心去访问 验证流程 api要确定的是这个token是否来自于鉴权中心的token? 如果是来自于鉴权中心的token,如何判断token是否失效? 这时候就需要用到加密技术 1. Des 对称可逆加密 2. Rsa 非对称可逆加密 对称可逆加密: 就是一个key,key可以加密,也必须使用这个key才能够解密 鉴权中心:key1 Api方法:key1 鉴权中心和api是同一个key; token验证流程: 1.用户在鉴权中心登录成功以后,可以使用key1加密;得到一段密文; 2.用户访问Api的时候,Api方就使用ke1去解密: 4.如果解密成功---防止抵赖(密文一定是来自于鉴权中心), 5.就进一步验证token是否过期, 6.如果过期就拦截,如果没有过期就通过 实际开发中:内网对称可逆加密,性能更优 外网:非对称可逆加密,更安全 JWT: 一对key, 二者无法相互推导; 私钥、公钥; 私钥-----鉴权中心;作为加密Key 公钥-----Api方法;作为解密key; Api方法只要是通过公钥能够解开密文;说明token是来自于鉴权中心 JWT验证流程 1.新增 JWT鉴权中心程序,配置相关逻辑(jwt一般是给的独立的程序和服务器)
2.http第一次登陆到鉴权中心,JWT通过用户名密码,使用非对称加密生成公钥和私钥保存在本地磁盘, 使用私钥生成加密key 把公钥文件给客户端 3.客户度拿到token令牌去访问Api的时候, api通过jwt给的公钥文件解密,解密成功就证明是jwt给的token,不成功则不是jwt给的toeken,之后得到相关信息
9.AJAX 携带token验证
前端代码如下
程序已经在中间件支持了跨域,但是会报错
1.还是会出现跨域报错
需要在statup.cs增加如下代码
2.并且还会请求两次
第一次请求报错,第二次请求 返回:204
解决如下:在statup.cs中间件里面增加如下代码,页面清楚缓存
10. identityservice4.0
1.如果鉴权中间是第三方,1.那么可能造成密码泄露 比如A 去请求第三方鉴权中心b 2.回收权限不方便
2.accesstoken,通行证
本文来自博客园,作者:12不懂3,转载请注明原文链接:https://www.cnblogs.com/LZXX/p/14705768.html