c# WebApi之身份验证:Basic基础认证

WebApi相关文章:

为什么需要身份认证

身份认证是为了提高接口访问的安全性,如果没有身份验证,那么任何匿名用户只要知道服务器的url,就可以随意访问服务器,从而访问或者操作数据库,这会是很恐怖的事。

什么是Basic基础认证

Basic基础认证是一种简单的用户名、密码验证过程,它的主要原理是加密用户信息,生成票据,每次需要身份验证时将票据带过来验证,实现步骤为:

  1. 用户登录,登录成功后将生成的票据返回到前端;
  2. 前端登录成功后,收到票据信息,跳转到主页面,并且吧票据一并带过去,存入Session;
  3. 在需要请求页面,把票据信息加入到请求的Head里面,将票据信息随着请求一起发送到服务端去;
  4. 在WebApi服务里面定义一个类,继承AuthorizeAttribute类,然后重写父类的OnAuthorization方法,在OnAuthorization方法里面取到当前http请求的Head,从Head里面取到我们前端传过来的票据信息。解密票据信息,从解密的信息里面得到用户名和密码,然后验证用户名和密码是否正确。如果正确,表示验证通过,否则返回自定义错误信息。
Basic基础认证的代码示例:

首先新建两个项目:Web测试站点、WebApi站点
这里写图片描述

1.1、在Web测试站点,添加一个登录页面:

<div style="text-align:center;">
        <div>用户名:<input type="text" id="txt_username" /></div>
        <div>密  码:<input type="password" id="txt_password" /></div>
        <div><input type="button" value="登录" id="btn_login" class="btn-default" /></div>
    </div>

登录请求的ajax:

 $(function () {
    $("#btn_login").click(function () {
        $.ajax({
            type: "get",
            url: "http://localhost:61593/api/account/login",
            data: { strUser: $("#txt_username").val(), strPwd: $("#txt_password").val() },
            success: function (data, status) {
                if (status == "success") {
                    if (!data.bRes) {
                        alert("登录失败");
                        return;
                    }
                    alert("登录成功");
                    //登录成功之后将用户名和用户票据带到主界面
                    window.location = "/Home/Index?UserName=" + data.UserName + "&Ticket=" + data.Ticket;

                }
            },
            error: function (e) {
            },
            complete: function () {

            }

        });
    });
});

1.2、对应的WebApi站点的,登录的Api接口:

/// <summary>
/// 用户登录
/// </summary>
/// <param name="strUser"></param>
/// <param name="strPwd"></param>
/// <returns></returns>
[HttpGet]
public object Login(string strUser, string strPwd)
{
    if (!ValidateUser(strUser, strPwd))
    {
        return new { bRes = false };
    }
    FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(0, strUser, DateTime.Now,
                    DateTime.Now.AddHours(1), true, string.Format("{0}&{1}", strUser, strPwd),
                    FormsAuthentication.FormsCookiePath);
    //返回登录结果、用户信息、用户验证票据信息
    var oUser = new UserInfo { bRes = true, UserName = strUser, Password = strPwd, Ticket = FormsAuthentication.Encrypt(ticket) };
    //将身份信息保存在session中,验证当前请求是否是有效请求
    HttpContext.Current.Session[strUser] = oUser;
    return oUser;
}

//校验用户名密码(正式环境中应该是数据库校验)
private bool ValidateUser(string strUser, string strPwd)
{
    if (strUser == "admin" && strPwd == "123456")
    {
        return true;
    }
    else
    {
        return false;
    }
}

自定义UserInfo实体:

public class UserInfo
{
    public bool bRes { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
    public string Ticket { get; set; }
}

新建的WebApi需要配置一下路由,打开App_Start文件夹下的WebApiConfig.cs文件,添加一条路由信息:

public static void Register(HttpConfiguration config)
{
    //解决跨域访问问题
    config.EnableCors(new EnableCorsAttribute("*", "*", "*"));

    // Web API 路由
    config.MapHttpAttributeRoutes();
    config.Routes.MapHttpRoute(
        name: "DefaultApi1",
        routeTemplate: "api/{controller}/{action}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}

如果是两个站点的话可能会出现跨域问题,解决跨域访问问题可以参考:
http://blog.csdn.net/lwpoor123/article/details/78457589

2.1、在Web测试站点添加一个用于跳转测试的index主页面

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <script src="~/Scripts/jquery-1.10.2.min.js"></script>
</head>
<body>
    测试结果:
    <div id="div_test">
        hello world
    </div>
    当前登录用户:
    <div id="username">
        @ViewBag.UserName
    </div>
</body>
</html>

ajax请求:

<script>
    var ApiUrl = "http://localhost:61593/";
    $(function () {
        $.ajax({
            type: "get",
            url: ApiUrl + "api/Account/GetAllData",
            data: {},
            beforeSend:function(XHR){                XHR.setRequestHeader('Authorization','BasicAuth @ViewBag.Ticket')
            },
            success: function (data, status) {
                if (status == "success") {
                    $("#div_test").html(data);
                }
            },
            error: function (e) {
                $("#div_test").html("Error");
            }
        });
    });
</script>

这里需要注意在beforeSend方法里面,向请求的报文头里面增加票据信息,用于把Ticket信息一同带到服务器:
XHR.setRequestHeader(‘Authorization’,’BasicAuth @ViewBag.Ticket’)
这里写图片描述

2.2、index页面的action,接收传递过来的票据数据,存入Session

public ActionResult Index(string UserName, string Ticket)
{
    if (UserName != null)
    {
        Session["UserName"] = UserName;
    }
    if (Ticket != null)
    {
        Session["Ticket"] = Ticket;
    }

    ViewBag.UserName = Session["UserName"];
    ViewBag.Ticket = Session["Ticket"];
    return View();
}

2.3、对应的Api接口:

public class AccountController : ApiController
{
    /// <summary>
    /// 得到所有数据
    /// </summary>
    /// <returns>返回数据</returns>
    [HttpGet]
    [RequestAuthorize]
    public string GetAllData()
    {
        return "Success";
    }
}

WebAip默认是没有开启Session,需要手动开启:
在WebApi站点,打开Global.asax文件,重写Init()方法

public override void Init()
{
    this.PostAuthenticateRequest += (sender, e) => HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
    base.Init();
}

或者:

public override void Init()
{
    PostAuthenticateRequest += MvcApplication_PostAuthenticateRequest;
    base.Init();
}

void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e)
{
    HttpContext.Current.SetSessionStateBehavior(
        SessionStateBehavior.Required);
}

3.1、WebApi身份验证部分(重点)
在WebApi站点,添加一个RequestAuthorizeAttribute.cs文件,继承AuthorizeAttribute,自定义此特性用于接口的身份验证:

 /// <summary>
/// 自定义此特性用于接口的身份验证
/// </summary>
public class RequestAuthorizeAttribute : AuthorizeAttribute
{
    //重写基类的验证方式,加入我们自定义的Ticket验证
    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        //从http请求的头里面获取身份验证信息,验证是否是请求发起方的ticket
        var authorization = actionContext.Request.Headers.Authorization;
        if ((authorization != null) && (authorization.Parameter != null))
        {
            //解密用户ticket,并校验用户名密码是否匹配
            var encryptTicket = authorization.Parameter;
            if (ValidateTicket(encryptTicket))
            {
                base.IsAuthorized(actionContext);
            }
            else
            {
                HandleUnauthorizedRequest(actionContext);
            }
        }
        //如果取不到身份验证信息,并且不允许匿名访问,则返回未验证401
        else
        {
            var attributes = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>();
            bool isAnonymous = attributes.Any(a => a is AllowAnonymousAttribute);
            if (isAnonymous) base.OnAuthorization(actionContext);
            else HandleUnauthorizedRequest(actionContext);
        }
    }

    protected override void HandleUnauthorizedRequest(HttpActionContext actioncontext)
    {
        base.HandleUnauthorizedRequest(actioncontext);

        var response = actioncontext.Response = actioncontext.Response ?? new HttpResponseMessage();
        response.StatusCode = HttpStatusCode.Forbidden;
        var content = new
        {
            code = -1,
            success = false,
            errs = new[] { "服务端拒绝访问:你没有权限,或者掉线了" }
        };
        response.Content = new StringContent(Json.Encode(content), Encoding.UTF8, "application/json");
    }

    //校验用户名密码(正式环境中应该是数据库校验)
    private bool ValidateTicket(string encryptTicket)
    {
        //解密Ticket
        var strTicket = FormsAuthentication.Decrypt(encryptTicket).UserData;

        //从Ticket里面获取用户名和密码
        var index = strTicket.IndexOf("&");
        string strUser = strTicket.Substring(0, index);
        string strPwd = strTicket.Substring(index + 1);

        if (strUser == "admin" && strPwd == "123456")
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

3.2、使用的时候只需要在控制器前面加上自定义的身份验证[RequestAuthorize]

/// <summary>
/// 得到所有数据
/// </summary>
/// <returns>返回数据</returns>
[HttpGet]
[RequestAuthorize]
public string GetAllData()
{
    return "Success";
}

这里写图片描述

这里写图片描述

这里写图片描述

如果不携带票据或者票据无效,服务端拒绝访问:
这里写图片描述

如果在控制器加了身份验证,有些请求又不想使用验证,可以在方法上面添加特性标注[AllowAnonymous]

[RequestAuthorize]
public class AccountController : ApiController
{
    /// <summary>
    /// 得到所有数据
    /// </summary>
    /// <returns>返回数据</returns>
    [HttpGet]
    public string GetAllData()
    {
        return "Success";
    }

    [AllowAnonymous]
    public string getData()
    {
        return "data";
    }
}
  • 4
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
目录 C#进阶系列——WebApi 路由机制剖析:你准备好了吗? ................................................................................................... 3 一、MVC和WebApi路由机制比较 ........................................................................................................................................ 5 1、MVC里面的路由 ......................................................................................................................................................... 5 2、WebApi里面的路由 ................................................................................................................................................... 5 二、WebApi路由基础 ............................................................................................................................................................. 7 1、默认路由 ..................................................................................................................................................................... 7 2、自定义路由 ............................................................................................................................................................... 10 2.1、自定义路由一:匹配到action ................................................................................................................. 11 2.2、自定义路由二 ............................................................................................................................................... 12 3、路由原理 ................................................................................................................................................................... 12 三、WebApi路由过程 ........................................................................................................................................................... 13 1、根据请求的url匹配路由模板 .............................................................................................................................. 13 2、找到控制器 ............................................................................................................................................................... 13 3、找到action ............................................................................................................................................................. 15 四、WebApi特性路由 ........................................................................................................................................................... 16 1、启动特性路由 ........................................................................................................................................................... 17 2、最简单的特性路由 ................................................................................................................................................... 17 3、带参数的特性路由 ................................................................................................................................................... 19 4、参数的约束和默认值 ............................................................................................................................................... 20 5、路由前缀 ................................................................................................................................................................... 20 五、第一个Restful风格的WebApi服务 ......................................................................................................................... 21 六、总结 ................................................................................................................................................................................. 22 C#进阶系列——WebApi 异常处理解决方案 ......................................................................................................................... 23 一、使用异常筛选器捕获所有异常 ..................................................................................................................................... 24 1、接口级别 ........................................................................................................................................................... 31 2、控制器级别 ....................................................................................................................................................... 33 3、全局配置 ........................................................................................................................................................... 34 二、HttpResponseException自定义异常信息 .............................................................................................................. 35 三、返回HttpError ............................................................................................................................................................ 37 四、总结 ................................................................................................................................................................................. 38 C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解 ......................................................................................... 39 一、void无返回值 ............................................................................................................................................................... 40 二、IHttpActionResult .................................................................................................................................................... 42 1、Json(T content) ........................................................................................................................................... 42 2、Ok()、 Ok(T content) ................................................................................................................................. 45 3、NotFound() ............................................................................................................................................................. 47 4、其他 ........................................................................................................................................................................... 49 4.1、Content(HttpStatusCode statusCode, T value) .................................................................. 49 4.2、BadRequest() ............................................................................................................................................ 49 4.3、Redirect(string location) ................................................................................................................ 50 5、自定义IHttpActionResult接口的实现 ............................................................................................................ 50 三、HttpResponseMessage ............................................................................................................................................... 53 四、自定义类型 ..................................................................................................................................................................... 54 五、总结 ................................................................................................................................................................................. 55 C#进阶系列——WebApi 接口参数不再困惑:传参详解 ..................................................................................................... 56 一、get请求 ......................................................................................................................................................................... 57 1、基础类型参数 ........................................................................................................................................................... 57 2、实体作为参数 ........................................................................................................................................................... 58 3、数组作为参数 ........................................................................................................................................................... 62 4、“怪异”的get请求 .................................................................................................................................................. 62 (1)WebApi的方法名称以get开头 ................................................................................................................ 62 (2)WebApi的方法名称不以get开头 ............................................................................................................ 64 二、post请求 ....................................................................................................................................................................... 66 1、基础类型参数 ........................................................................................................................................................... 66 (1)错误的写法 ................................................................................................................................................... 66 (2)正确的用法 ................................................................................................................................................... 67 (1)错误写法 ....................................................................................................................................................... 68 (2)正确用法 ....................................................................................................................................................... 69 (3)推荐用法 ....................................................................................................................................................... 70 2、实体作为参数 ........................................................................................................................................................... 70 (1)单个实体作为参数 ....................................................................................................................................... 70 (2)实体和基础类型一起作为参数传递 ........................................................................................................... 73 3、数组作为参数 ........................................................................................................................................................... 74 (1)基础类型数组 ............................................................................................................................................... 74 (2)实体集合 ....................................................................................................................................................... 74 4、后台发送请求参数的传递 ....................................................................................................................................... 75 三、put请求 ......................................................................................................................................................................... 77 1、基础类型参数 ........................................................................................................................................................... 77 2、实体作为参数 ........................................................................................................................................................... 77 3、数组作为参数 ........................................................................................................................................................... 78 四、delete请求 ................................................................................................................................................................... 78 五、总结 ................................................................................................................................................................................. 79 C#进阶系列——WebApi 身份认证解决方案:Basic基础认证.......................................................................................... 80 一、为什么需要身份认证 ..................................................................................................................................................... 81 1、我们不加身份认证,匿名用户可以直接通过url随意访问接口: ........................................................... 81 2、增加了身份认证之后,只有带了我们访问票据的请求才能访问我们的接口。 ....................................... 82 二、Basic基础认证的原理解析 ......................................................................................................................................... 84 1、常见的认证方式 ....................................................................................................................................................... 84 2、Basic基础认证原理 ............................................................................................................................................... 85 三、Basic基础认证的代码示例 ......................................................................................................................................... 85 1、登录过程 ................................................................................................................................................................... 85 1.1、Web前端 ....................................................................................................................................................... 85 1.2、登录的API接口 .......................................................................................................................................... 86 2、/Home/Index主界面 .............................................................................................................................................. 88 3、WebApiCORS验证部分(重点) ............................................................................................................................ 90 3.1、在WebApiCORS项目里面自定义一个类RequestAuthorizeAttribute,去继承我们的AuthorizeAttribute这个类。然后重写OnAuthorization方法,在这个方法里面取到请求头的Ticket信息,然后校验用户名密码是否合理。 ............................................................................................................. 90 3.2、在具体的Api接口增加我们上面自定义类的特性 .................................................................................. 91 四、优化 ................................................................................................................................................................................. 92 1、解决API的问题 ...................................................................................................................................................... 92 2、解决ajax的问题 .................................................................................................................................................... 93 3、解决特殊不想使用验证的方法 ............................................................................................................................... 94 五、总结 ................................................................................................................................................................................. 95 C#进阶系列——WebApi 跨域问题解决方案:CORS ............................................................................................................. 95 一、跨域问题的由来 ............................................................................................................................................................. 96 二、跨域问题解决原理 ......................................................................................................................................................... 96 三、跨域问题解决细节 ......................................................................................................................................................... 96 1、场景描述 ................................................................................................................................................................... 97 2、场景测试 ................................................................................................................................................................... 99 1)我们不做任何的处理,直接将两个项目运行起来。看效果如何 ............................................................... 99 2)使用CORS跨域 ................................................................................................................................................ 99 3)CORS的具体参数设置。 ............................................................................................................................... 103 四、总结 ............................................................................................................................................................................... 104 C#进阶系列——WebApi 接口测试工具:WebApiTestClient ........................................................................................ 105 一、WebApiTestClient介绍 ........................................................................................................................................... 106 二、WebApiTestClient展示 ........................................................................................................................................... 106 三、WebApiTestClient使用 ........................................................................................................................................... 116 1、如何引入组件 ......................................................................................................................................................... 116 2、如何使用组件 ......................................................................................................................................................... 118 1、修改Api.cshtml文件 ................................................................................................................................. 118 2、配置读取注释的xml路径 ............................................................................................................................ 119 3、测试接口 ......................................................................................................................................................... 121 四、总结 ............................................................................................................................................................................... 123
以下是一个 C# WebAPI 中实现 Header 验证的示例代码: ```csharp public class HeaderAuthenticationFilter : IAuthenticationFilter { private readonly string apiKey = "your_api_key_here"; public bool AllowMultiple => false; public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken) { // 获取请求头的 Authorization 字段 var authHeader = context.Request.Headers.Authorization; // 如果 Authorization 字段不存在或不是 Bearer 形式的 Token,则返回未授权的错误 if (authHeader == null || !authHeader.Scheme.Equals("Bearer", StringComparison.OrdinalIgnoreCase)) { context.ErrorResult = new AuthenticationFailureResult("Unauthorized", context.Request); return; } // 获取 Token var token = authHeader.Parameter; // 验证 Token 是否正确 if (string.IsNullOrWhiteSpace(token) || !token.Equals(apiKey)) { context.ErrorResult = new AuthenticationFailureResult("Unauthorized", context.Request); return; } // 设置用户身份验证信息 var identity = new GenericIdentity("user"); context.Principal = new GenericPrincipal(identity, new string[] { }); } public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken) { return Task.FromResult(0); } } public class AuthenticationFailureResult : IHttpActionResult { public string ReasonPhrase { get; private set; } public HttpRequestMessage Request { get; private set; } public AuthenticationFailureResult(string reasonPhrase, HttpRequestMessage request) { ReasonPhrase = reasonPhrase; Request = request; } public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) { var response = new HttpResponseMessage(HttpStatusCode.Unauthorized); response.RequestMessage = Request; response.ReasonPhrase = ReasonPhrase; return Task.FromResult(response); } } ``` 在上述代码中,我们创建了一个名为 `HeaderAuthenticationFilter` 的类,该类实现了 `IAuthenticationFilter` 接口,用于在 WebAPI 的管道中进行身份验证。我们在 `AuthenticateAsync` 方法中进行身份验证,如果验证失败,则设置 `ErrorResult` 属性返回未授权的错误。如果验证成功,则设置 `Principal` 属性为一个包含用户信息的 `IPrincipal` 对象。最后,我们创建了一个名为 `AuthenticationFailureResult` 的类,该类实现了 `IHttpActionResult` 接口,用于返回错误响应。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YuanlongWang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值