WebApi使用JWT认证(一)

这是第一部:先实现NetFramework上的WebApi使用JWT认证

1、VS新建一个WebApi项目
在这里插入图片描述
2、项目右键----管理Nuget程序包----找到JWT,然后安装
在这里插入图片描述
3、Model文件夹下新建三个类LoginResult,LoginRequest,AuthInfo

namespace JwtWebApi.Models
{
    public class LoginResult
    {
        public bool Success { get; set; }

        public string Token { get; set; }

        public string Message { get; set; }
    }
}
namespace JwtWebApi.Models
{
    public class LoginRequest
    {
        public string UserName { get; set; }

        public string Password { get; set; }
    }
}
using System.Collections.Generic;

namespace JwtWebApi.Models
{
    public class AuthInfo
    {
        //模拟JWT的payload
        public string UserName { get; set; }

        public List<string> Roles { get; set; }

        public bool IsAdmin { get; set; }
    }
}

4、在Controllers文件夹中的HomeController(没有就新建一个)中添加一个Post方法,这是生成JWT Token方法的地方,一般应放在登录的Action

using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using JwtWebApi.Models;
using System;
using System.Collections.Generic;
using System.Web.Http;

namespace JwtWebApi.Controllers
{
    public class HomeController : ApiController
    {
        public LoginResult Post([FromBody]LoginRequest request)
        {
            LoginResult rs = new LoginResult();
            //这是是获取用户名和密码的,这里只是为了模拟
            if (request.UserName == "wangshibang" && request.Password == "123456")
            {
                AuthInfo info = new AuthInfo { UserName = "wangshibang", Roles = new List<string> { "Admin", "Manage" }, IsAdmin = true };
                try
                {
                    const string secret = "To Live is to change the world";
                    //secret需要加密
                    IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
                    IJsonSerializer serializer = new JsonNetSerializer();
                    IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                    IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
                    var token = encoder.Encode(info, secret);
                    rs.Message = "XXXXX";
                    rs.Token = token;
                    rs.Success = true;
                }
                catch (Exception ex)
                {
                    rs.Message = ex.Message;
                    rs.Success = false;
                }
            }
            else
            {
                rs.Message = "fail";
                rs.Success = false;
            }
            return rs;
        }
    }
}

5、项目下添加一个Attributes文件夹,需要写个权限拦截器,新建一个ApiAuthorizeAttribute类继承自AuthorizeAttribute

using JWT;
using JWT.Serializers;
using JwtWebApi.Models;
using System;
using System.Linq;
using System.Web.Http;
using System.Web.Http.Controllers;

namespace JwtWebApi.Attributes
{
    public class ApiAuthorizeAttribute : AuthorizeAttribute
    {
        protected override bool IsAuthorized(HttpActionContext actionContext)
        {
            var authHeader = from t in actionContext.Request.Headers where t.Key == "auth" select t.Value.FirstOrDefault();
            if (authHeader != null)
            {
                string token = authHeader.FirstOrDefault();
                if (!string.IsNullOrEmpty(token))
                {
                    try
                    {
                        const string secret = "To Live is to change the world";
                        //secret需要加密
                        IJsonSerializer serializer = new JsonNetSerializer();
                        IDateTimeProvider provider = new UtcDateTimeProvider();
                        IJwtValidator validator = new JwtValidator(serializer, provider);
                        IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                        IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder);

                        var json = decoder.DecodeToObject<AuthInfo>(token, secret, verify: true);
                        if (json != null)
                        {
                            actionContext.RequestContext.RouteData.Values.Add("auth", json);
                            return true;
                        }
                        return false;
                    }
                    catch (Exception ex)
                    {
                        return false;
                    }
                }
            }
            return false;
        }
    }
}

6、Controllers文件夹中新建一个UserController,新建一个GetAction,需要加上ApiAuthorize特性

using JwtWebApi.Attributes;
using JwtWebApi.Models;
using System.Web.Http;

namespace JwtWebApi.Controllers
{
    public class UserController : ApiController
    {
        // GET: User
        [ApiAuthorize]
        public string Get()
        {
            AuthInfo info = RequestContext.RouteData.Values["auth"] as AuthInfo;
            if (info == null)
            {
                return "获取不到,失败";
            }
            else
            {
                return $"获取到了,Auth的Name是 {info.UserName}";
            }
        }
    }
}

7、然后用PostMan测试

下面是解决接口调用的跨域问题,有两种,一种是用CORS,另外一种就是修改WebConfig添加自定义options谓词处理模块

我只用了自定义Options谓词处理

<system.webServer>
    <handlers>
      <!--开启options谓词处理模块-->
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <!--<remove name="OPTIONSVerbHandler" />-->
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
    <httpProtocol>
      <customHeaders>
        <!--添加自定义options谓词处理模块-->
        <add name="Access-Control-Allow-Origin" value="http://localhost:8057"/>
        <add name="Access-Control-Allow-Headers" value="accept, auth"/>
        <add name="Access-Control-Allow-Methods" value="GET, OPTIONS"/>
      </customHeaders>
    </httpProtocol>
    <validation validateIntegratedModeConfiguration="false" />
    <modules>
      <remove name="ApplicationInsightsWebTracking" />
      <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" />
    </modules>
  </system.webServer>

好了,现在把你的WebApi部署到服务器上,然后用另一个跨域页面调取接口访问吧

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <meta charset="utf-8" />
    <script src="jquery-3.3.1.min.js"></script>
</head>
<body>
    <fieldset>
        <legend>身份验证</legend>
        <form>
            <label for="UserName">用户名:</label><input type="text" name="userName" id="userName" value="admin" />
            <br />
            <br />
            <label for="Password">密码:</label><input type="password" name="password" id="password" value="123" />
            <br />
            <br />
        </form>
        <button id="login">登录</button>
    </fieldset>
    <br />

    <fieldset>
        <legend>调用接口</legend>
        <button id="invoke">调用接口</button>
    </fieldset>
    <script>
        $(function () {
            //调用api站点的登录接口,接口在登录成功后返回一个token。
            $("#login").on("click", function () {
                $.ajax({
                    url: "http://localhost:8056/api/home",
                    data: $("form").serialize(),
                    method: "post",
                    success: function (data) {
                        if (data.Success) {
                            //为简单起见,将token保存在全局变量中。
                            window.token = data.Token;
                            alert("登录成功");
                        } else {
                            alert("登录失败:" + data.Message);
                        }
                    }
                });
            });

            //调用api站点的获取数据的接口,该接口要求身份验证。
            $("#invoke").on("click", function () {
                console.log(window.token);
                $.ajax({
                    url: "http://localhost:8056/api/user",
                    method: "get",
                    headers: { "auth": window.token },//通过请求头来发送token,放弃了通过cookie的发送方式
                    complete: function (jqXHR,textStatus) {
                        alert(jqXHR.responseText);
                    },

                });
            });
        });
    </script>
</body>
</html>
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值