```handlebars
前端登录代码:
<script src="js/tableserialize.js"></script>
<script type="text/javascript">
//获取登录信息
$("#form1 input[type='submit']").click(function () {
var getform1 = $("#form1").serializeObject();
alert(JSON.stringify(getform1));
var url = "http://localhost:59110/api/user/Login";
$.ajax({
url: url,
type: "post",
data:JSON.stringify(getform1)),
dataType: "json",//json写了jq会帮我们转换成数组或者对象 他已经用JSON.parse弄好了
contentType: 'application/json;charset=utf-8', //服务器返回json格式数据
success: function (data) {
if (data.Code == 200) {
alert("成功!" + JSON.stringify(data));
sessionStorage.setItem("token", data.Data);
}
},
error: function (err) {
alert("出错了!" + JSON.stringify(err));
}
});
})
//获取用户信息
$("#getuserInfo").click(function () {
var token = sessionStorage.getItem("token");
alert(token);
if (token == null || token == "") {
return true;
}
var url = "/api/user/UserInfo";
$.ajax({
url: url,
type: "get",
headers: {
token: token
},
success: function (data) {
console.log(JSON.stringify(data));
if (data != null) {
alert("请求成功:" + JSON.stringify(data));
}
},
error: function (err) {
alert("出错了:" + JSON.stringify(err));
}
});
})
</script>
提供 表单序列化的js:tableserialize.js
; (function ($) {
jQuery.prototype.serializeObject = function () {
var obj = new Object();
$.each(this.serializeArray(), function (index, param) {
if (!(param.name in obj)) {
obj[param.name] = param.value;
}
});
return obj;
};
})(jQuery);
后台代码:
api部分:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebApiDemoTest.Models;
using myapi.Filters;
using myapi.Models;
using myapi.Models.Auth;
namespace myapi.Controllers
{
/*
* 1.通过特性的方式进行JWT验证。
*
* 2.在验证过程中获取jwt的账号信息并存入User.Identity.Name
*
* 3.可以在任意Action 方法中读取User.Identity.Name 属性里的值
*
*
* 特性与 过滤器 auth
*
*/
[RoutePrefix(prefix:"api/user")]
public class userController : ApiController
{
[Route(template:"Login")]
[MyAuth] //验证操作
public IHttpActionResult Login(Login_model login_)
{
if (ModelState.IsValid)//t通过校验
{
return Ok(new ResponseData() {
Data = jwtTools.Encoder(new Dictionary<string, object>()
{
{"LoginName",login_.userName },
{"UserId",12354 },
})
});
}
else//通过失败
{
return Ok(new Models.ResponseData() { Code = 500, Errmessage = "账号或密码有误" });
}
}
/// <summary>
/// 得到用户信息
/// </summary>
/// <returns></returns>
[MyAuth]
[HttpGet]
[Route(template: "UserInfo")]
public IHttpActionResult GetUserInfo()
{
// 强烈推荐使用ID操作
//先去数据库获取ID,可以通过ID获取想要的值
//其他操作
return Ok(new ResponseData()
{
Data = ((UserIdentity)User.Identity).UserId
}) ;
}
}
}
没有引用core,记得引用才得行,
注: // Web API 配置和服务 ,需要配置才可以跨域
config.EnableCors(new EnableCorsAttribute("", "", “*”));
jwt加密部分:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using Newtonsoft.Json;
using JWT.Exceptions;
namespace myapi.Models
{
public class jwtTools
{
public static string Key { get; set; } = "Hello World";
static IJwtAlgorithm algorithm = new HMACSHA256Algorithm();//HMACSHA256加密
static IJsonSerializer serializer = new JsonNetSerializer();//序列化和反序列
static IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();//Base64编解码
static IDateTimeProvider provider = new UtcDateTimeProvider();//UTC时间获取
/// <summary>
/// jwt加密
/// </summary>
/// <param name="payload"></param>
/// <param name="key"></param>
/// <returns></returns>
public static string Encoder(Dictionary<string,object> payload, string key=null)
{
if (string.IsNullOrEmpty(key))
{
key = Key;
}
//添加jwt的一个时效串
payload.Add("timeout", DateTime.Now.AddDays(1));
IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
return encoder.Encode(payload, key);
}
/// <summary>
/// jwt解密
/// </summary>
/// <param name="jwtStr"></param>
/// <param name="key"></param>
/// <returns></returns>
public static Dictionary<string,object > Decode(string jwtStr,string key=null)
{
if (string.IsNullOrEmpty(key))
{
key = Key;
}
try
{
IJwtValidator validator = new JwtValidator(serializer, provider);//用于验证JWT的类
IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm);//用于解析JWT的类
var json = decoder.Decode(token:jwtStr, key, verify: true);//verify:true表示解析JWT时进行验证,该方法会自动调用validator的Validate()方法,不满足验证会抛出异常,因此我们不用写验证的方法
//string 转换为Dictionary 反向转换为对象内容
var result = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
if ((DateTime)result["timeout"] < DateTime.Now)
throw new Exception(message: "jwt已经过期,请重新登录");
result.Remove(key:"timeout");//删除里面的key等于timeout值
return result;
}
catch (TokenExpiredException)//如果当前时间大于负载中的过期时间(负荷中的exp),引发Token过期异常
{
throw new Exception(message: "jwt已经过期,请重新登录");
}
catch (SignatureVerificationException)//如果签名不匹配,引发签名验证异常
{
throw new Exception(message: "Token签名不正确!");
}
catch (Exception)
{
throw;
}
}
}
}
注:这里是需要引用jwt, 才可进行操作,不然报错
登录验证类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
namespace WebApiDemoTest.Models
{
public class Login_model
{
/// <summary>
/// 用户名
/// </summary>
[Required] //也可以用在界面上
[EmailAddress]
[StringLength(maximumLength:100,MinimumLength =5)]
public string userName { get; set; }
/// <summary>
/// 用户密码
/// </summary>
[Required]
[StringLength(maximumLength:30,MinimumLength =6)]
public string userPwd { get; set; }
}
}
注:这里需要验证,提高登录安全度
信息响应类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace myapi.Models
{
public class ResponseData
{
public int Code { get; set; } = 200;
public object Data { get; set; }
public string Errmessage { get; set; }
}
}
验证登录类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using myapi.Models;
using System.Net;
using System.Web.Http;
using myapi.Models.Auth;
namespace myapi.Filters
{
public class MyAuthAttribute : Attribute, IAuthorizationFilter
{
public bool AllowMultiple => throw new NotImplementedException();
/// <summary>
/// 前端响应返回的数据
/// </summary>
/// <param name="actionContext">请求返回的内容</param>
/// <param name="cancellationToken">请求返回的token</param>
/// <param name="continuation">异步返回的结果</param>
/// <returns></returns>
public async Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
{
IEnumerable<string> headers;
//验证jwt
//如果指定的标头和指定的值存储在 System.Net.Http.Headers.HttpHeaders 集合中,则返回。
if (actionContext.Request.Headers.TryGetValues(name: "token", out headers))
{
var loginName = jwtTools.Decode(jwtStr: headers.First())["LoginName"].ToString();
var UserId = jwtTools.Decode(jwtStr: headers.First())["UserId"].ToString();
(actionContext.ControllerContext.Controller as ApiController).User = new ApplicationUser(loginName, Convert.ToInt32(UserId));
return await continuation();
}
// 如果不成功返回 ( 等效于 HTTP 状态 401。 System.Net.HttpStatusCode.Unauthorized 指示所请求的资源需要身份验证)
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
}
}
}
注:这里是获取信息时,得到登录时加入header值,获取用户信息。
要获取的接口类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Principal;
namespace myapi.Models.Auth
{
public class UserIdentity : IIdentity
{
/// <summary>
/// 构造方法 获取name userId的值
/// </summary>
/// <param name="name"></param>
/// <param name="userId"></param>
public UserIdentity(string name,int userId)
{
Name = name;
UserId = userId;
}
public string Name { get; }
public int UserId { get; }
public string AuthenticationType { get; }
public bool IsAuthenticated { get; }
}
public class ApplicationUser : IPrincipal
{
public ApplicationUser(string name,int UserId)
{
Identity = new UserIdentity(name, UserId);
}
public IIdentity Identity { get; }
public bool IsInRole(string role)
{
throw new NotImplementedException();
}
}
}
链接起来基本就是一个完整的实体:
有兴趣的可以试试,也可以咨询我。
没加入数据库,可以自己配置下数据库就可以了。
结果演示:
可以看到值取到了,可以去通过token,取到用户信息。