……

WebApi Basic基础身份认证

 

一:为什么需要身份认证

没有身份认证,匿名用户只要知道了我们服务的url,就能随意访问接口

 

 

增加了身份认证后,只有拿到票据的请求才能访问接口

 

 

 

下面是代码示例

 

WEB前端

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head>

</head>
<body style="">
    <canvas class="pg-canvas" width="1536" height="310"></canvas>
    <div class="login">
        <div class="login_title">
            <span>管理员登录</span>
        </div>
        <div class="login_fields">
            <div class="login_fields__user">
                <div class="icon">
                    <img alt="" src="/Admin/img/user_icon_copy.png">
                </div>
                <input name="login" placeholder="用户名" maxlength="16" type="text" autocomplete="off" value="admin">
                <div class="validation">
                    <img alt="" src="/Admin/img/tick.png">
                </div>
            </div>
            <div class="login_fields__password">
                <div class="icon">
                    <img alt="" src="/Admin/img/lock_icon_copy.png">
                </div>
                <input name="pwd" placeholder="密码" maxlength="16" type="text" autocomplete="off">
                <div class="validation">
                    <img alt="" src="/Admin/img/tick.png">
                </div>
            </div>
            <div class="login_fields__password">
                <div class="icon">
                    <img alt="" src="/Admin/img/key.png">
                </div>
                <input name="code" placeholder="验证码" maxlength="4" type="text" autocomplete="off">
                <div class="validation" style="opacity: 1; right: -5px; top: -3px;">
                    <canvas class="J_codeimg" id="myCanvas" onclick="Code();">对不起,您的浏览器不支持canvas,请下载最新版浏览器!</canvas>
                </div>
            </div>
            <div class="login_fields__submit">
                <input type="button" value="登录">
            </div>
        </div>
        <div class="success">
        
        </div>
        <div class="disclaimer">
            <p>欢迎登陆后台管理系统 </p>
            <%--<p style="text-align:right;"><a href="Register.aspx" style="color:white;">注册</a></p>--%>
        </div>
    </div>
    <div class="authent">
        <div class="loader" style="height: 44px; width: 44px; margin-left: 28px;">
            <div class="loader-inner ball-clip-rotate-multiple">
                <div></div>
                <div></div>
                <div></div>
            </div>
        </div>
        <p>认证中...</p>
    </div>
    <div class="OverWindows"></div>

    <script type="text/javascript">
        var canGetCookie = 0; //是否支持存储Cookie 0 不支持 1 支持
        var ajaxmockjax = 1; //是否启用虚拟Ajax的请求响 0 不启用  1 启用
        //默认账号密码

        var truelogin = "admin";
        var truepwd = "123456";

        var CodeVal = 0;
        Code();
        function Code() {
            if (canGetCookie == 1) {
                createCode("AdminCode");
                var AdminCode = getCookieValue("AdminCode");
                showCheck(AdminCode);
            } else {
                showCheck(createCode(""));
            }
        }
        function showCheck(a) {
            CodeVal = a;
            var c = document.getElementById("myCanvas");
            var ctx = c.getContext("2d");
            ctx.clearRect(0, 0, 1000, 1000);
            ctx.font = "80px 'Hiragino Sans GB'";
            ctx.fillStyle = "#E8DFE8";
            ctx.fillText(a, 0, 100);
        }
        $(document).keypress(function (e) {
            // 回车键事件  
            if (e.which == 13) {
                $('input[type="button"]').click();
            }
        });
        //粒子背景特效
        $('body').particleground({
            dotColor: '#E8DFE8',
            lineColor: '#133b88'
        });
        $('input[name="pwd"]').focus(function () {
            $(this).attr('type', 'password');
        });
        $('input[type="text"]').focus(function () {
            $(this).prev().animate({ 'opacity': '1' }, 200);
        });
        $('input[type="text"],input[type="password"]').blur(function () {
            $(this).prev().animate({ 'opacity': '.5' }, 200);
        });
        $('input[name="login"],input[name="pwd"]').keyup(function () {
            var Len = $(this).val().length;
            if (!$(this).val() == '' && Len >= 5) {
                $(this).next().animate({
                    'opacity': '1',
                    'right': '30'
                }, 200);
            } else {
                $(this).next().animate({
                    'opacity': '0',
                    'right': '20'
                }, 200);
            }
        });
        var open = 0;
        layui.use('layer', function () {
            //var msgalert = '默认账号:' + truelogin + '<br/> 默认密码:' + truepwd;
            //var index = layer.alert(msgalert, { icon: 6, time: 4000, offset: 't', closeBtn: 0, title: '友情提示', btn: [], anim: 2, shade: 0 });
            //layer.style(index, {
            //    color: '#777'
            //});
            //非空验证
            $('input[type="button"]').click(function () {
                var login = $('input[name="login"]').val();
                var pwd = $('input[name="pwd"]').val();
                var code = $('input[name="code"]').val();
                if (login == '') {
                    ErroAlert('请输入您的账号');
                } else if (pwd == '') {
                    ErroAlert('请输入密码');
                } else if (code == '' || code.length != 4) {
                    ErroAlert('输入验证码');
                } else {
                    //认证中..
                    fullscreen();
                    $('.login').addClass('test'); //倾斜特效
                    setTimeout(function () {
                        $('.login').addClass('testtwo'); //平移特效
                    }, 300);
                    setTimeout(function () {
                        $('.authent').show().animate({ right: -320 }, {
                            easing: 'easeOutQuint',
                            duration: 600,
                            queue: false
                        });
                        $('.authent').animate({ opacity: 1 }, {
                            duration: 200,
                            queue: false
                        }).addClass('visible');
                    }, 500);

                    //登陆
                    var JsonData = { login: login, pwd: pwd, code: code };
                    //此处做为ajax内部判断
                    var url = "";
                    if (JsonData.code.toUpperCase() == CodeVal.toUpperCase()) {
                        url = "/Tools/Login.ashx";
                    } else {
                        url = "Ajax/LoginFalse";
                    }


                    AjaxPost(url, JsonData,
                        function () {
                            //ajax加载中
                        },
                        function (data) {
                            console.log(data);
                            //ajax返回 
                            //认证完成
                            setTimeout(function () {
                                $('.authent').show().animate({ right: 90 }, {
                                    easing: 'easeOutQuint',
                                    duration: 600,
                                    queue: false
                                });
                                $('.authent').animate({ opacity: 0 }, {
                                    duration: 200,
                                    queue: false
                                }).addClass('visible');
                                $('.login').removeClass('testtwo'); //平移特效
                            }, 2000);
                            setTimeout(function () {
                                $('.authent').hide();
                                $('.login').removeClass('test');
                                if (data.Status == 'ok') {
                                    //登录成功
                                    $('.login div').fadeOut(100);
                                    $('.success').fadeIn(1000);
                                    $('.success').html(data.Text);
                                    //跳转操作
                                    
                                    location.href = "Admin_index.aspx"
                                } else {
                                    AjaxErro(data);
                                }
                            }, 2400);
                        })
                }
            })
        })
        var fullscreen = function () {
            elem = document.body;
            if (elem.webkitRequestFullScreen) {
                elem.webkitRequestFullScreen();
            } else if (elem.mozRequestFullScreen) {
                elem.mozRequestFullScreen();
            } else if (elem.requestFullScreen) {
                elem.requestFullscreen();
            } else {
                //浏览器不支持全屏API或已被禁用  
            }
        }
        if (ajaxmockjax == 1) {
            $.mockjax({
                url: 'Ajax/Login',
                status: 200,
                responseTime: 50,
                responseText: { "Status": "ok", "Text": "登陆成功<br /><br />欢迎回来" }
            });
            $.mockjax({
                url: 'Ajax/LoginFalse',
                status: 200,
                responseTime: 50,
                responseText: { "Status": "Erro", "Erro": "账号名或密码或验证码有误" }
            });
        }
    </script>


    <div class="layui-layer-move"></div>
</body>
</html>

  登录API接口

namespace SW163WebClient.Controllers
{
    /// <summary>
    /// ==========2022-6-1(小金)===============
    /// </summary>
    public class UserController : ApiController
    {
        /// <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;
        }

        public void ProcessRequest(HttpContext context)
        {
            throw new NotImplementedException();
        }

        //校验用户名密码
        private bool ValidateUser(string strUser, string strPwd)
        {
            SW163BLL.Administrators blladmin = new SW163BLL.Administrators();
            DataTable dt = blladmin.GetList("UserName='" + strUser + "' and PassWord='" + SW163Common.DESEncrypt.Encrypt(strPwd) + "'").Tables[0];
            if (dt.Rows.Count > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }

    public class UserInfo
    {
        public bool bRes { get; set; }

        public string UserName { get; set; }

        public string Password { get; set; }

        public string Ticket { get; set; }
    }
}

 Home/Index.aspx界面

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace SW163WebClient.Admin
{
    /// <summary>
    /// 2022-6-1 小金
    /// </summary>
    public partial class Index: System.Web.UI.Page
    {
        public SW163UI.BasePage bg = new SW163UI.BasePage();
        public string UserName = string.Empty;
        public string Ticket = string.Empty;
        public int first = 1;
        protected void Page_Load(object sender, EventArgs e)
        {
            HttpCookie myCookie = HttpContext.Current.Request.Cookies["Web"];
            if (bg.CookieYESNo()) { Response.Redirect("Login.aspx"); }
            else
            {
                if (myCookie["UserName"] != null && myCookie["Ticket"] != null && myCookie["date"] != null)
                {
                    UserName = myCookie["UserName"];
                    Ticket = myCookie["Ticket"];
                    //第一次登录时间和当前时间对比,大于30分钟清除cookie;
                    DateTime time = Convert.ToDateTime(myCookie["date"]);
                    DateTime time1 = DateTime.Now;
                    TimeSpan timeSpan = time1 - time;
                    if (timeSpan.TotalMinutes >= 30)
                    {
                        UserName = "";
                        Ticket = "";
                        bg.ExitCookie();

                    }
                    else
                    {
                        //当前时间大于第一次登录时间1分钟,非第一次登录
                        if (Convert.ToDateTime(time1.ToString("yyyy-MM-dd HH:mm")) > Convert.ToDateTime(time.ToString("yyyy-MM-dd HH:mm")))
                        {
                            first = 2;
                            myCookie["Ticket"] = "2";
                        }


                    }
                }
                else
                {
                    bg.ExitCookie();
                    Response.Redirect("Login.aspx");
                }
            }
        }

        //退出登录
        protected void lbtnExit_Click(object sender, EventArgs e)
        {
            bg.ExitCookie();
        }
    }
}
<head>
    <meta charset="utf-8">
    <script type="text/javascript" src="js/jquery.min.js"></script>
     <script type="text/javascript">
         //打开页面的时候保存票据信息
         var UserName ="<%=UserName %>";
         var Ticket = "<%=Ticket%>";
         var first =<%=first%>;
     </script>
</head>

 <script>
        $(function () {
            $.ajax({
                type: "get",
                url: "/api/Charging/GetAllChargingData",
                data: {},
                beforeSend: function (XHR) {
                    //发送ajax请求之前向http的head里面加入验证信息
                    XHR.setRequestHeader('Authorization', 'BasicAuth ' + Ticket);
                },
                success: function (data, status) {
                    if (status == "success") {
                        if (first==1) {
                            layer.alert(UserName + ":欢迎回家!");
                        }
                    }
                },
                error: function (e) {

                     layer.alert("认证信息已过期!请重新登录", function () {
                        //清除kooie
                         $.ajax({
                             type: "post",
                             url: "/Tools/Login.ashx",
                             data: { "act":"clean_up"},
                             success: function (result)
                             {
                                 window.location.href = "Login.aspx";
                             }
                         })
                       
                    });
                },
                complete: function () {

                }

            });
        });

    </script>

WebAPI项目里面自定义一个类RequestAuthorizeAttribute,去继承AuthorizeAttribute这个类。然后重写OnAuthorization方法,在这个方法里面取到请求头的Ticket信息,再效验用户名和密码是否正确

/// <summary>
    /// ==========2022-6-1(小金)===============
    /// 自定义此特性用于接口的身份验证
    /// </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);
            }
        }

        //校验用户名密码
        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);

            SW163BLL.Administrators blladmin = new SW163BLL.Administrators();
            DataTable dt = blladmin.GetList("UserName='" + strUser + "' and PassWord='" + SW163Common.DESEncrypt.Encrypt(strPwd) + "'").Tables[0];
            if (dt.Rows.Count > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }

在具体的Api接口增加我们上面定义的自定义特性

/// <summary>
    /// ==========2022-6-1(小金)===============
    /// </summary>
    public class ChargingController : BaseApiController
    {
        /// <summary>
        /// 得到所有数据
        /// </summary>
        /// <returns>返回数据</returns>
        [HttpGet,Route("api/Charging/GetAllChargingData")]
        public string GetAllChargingData()
        {
            return "Success";
        }

        /// <summary>
        /// 得到当前Id的所有数据
        /// </summary>
        /// <param name="id">参数Id</param>
        /// <returns>返回数据</returns>
        [HttpGet, Route("api/Charging/GetAllChargingData")]
        public string GetAllChargingData(string id)
        {
            return "ChargingData" + id;
        }
    }

在API添加身份认证公共父类,子类只需继承父类认证即可

/// <summary>
    /// API 身份认证公共父类
    /// 
    /// ==========2022-6-1(小金)===============
    /// 
    /// origins配置允许访问的域名,多个域名以逗号分隔即可,域名一定要完整,
    /// 如果是ip地址前面要加上“http”,只使用IP的话一定会失效的。
    /// 参数headers配置所支持的资源。
    /// 参数methods配置支持的方法,get、post、put等。
    /// 如果允许任意域名、任意资源、任意方法访问自己的webapi,则三个参数全部使用星号”*”即可
    /// </summary>
    [RequestAuthorize]
    [EnableCors(origins: "*", headers: "*", methods: "*")]
    public class BaseApiController : ApiController
    {
    }

 

 

本文转自:https://www.cnblogs.com/landeanfen/p/5287064.html

 

posted @ 2022-06-10 10:30  粉香地瓜  阅读(174)  评论(0)    收藏  举报