WebApi-授权问题

发布于 2020-10-20  173 次阅读


1、用户登录后才能访问到的数据,例如购物车,个人信息等

2、关于授权下面我使用的是 AuthorizeAttribute

前台登录页面

1、Login

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录</title>
</head>
<body>
    姓名<input type="text" name="uname" id="uname">
    密码<input type="text" name="upwd" id="upwd">
    <input type="button" name="buton" id="btn" value="点我发送">
</body>
<script src="jquery-3.2.1.js"></script>
<script>
 $(function(){
     $("#btn").click(function(){
         $.ajax({
             url:&#039;http://localhost:2108/api/Userinfo/login&#039;,
             type:&#039;post&#039;,
             data:{&#039;uname&#039;:$("#uname").val(),&#039;upwd&#039;:$("#upwd").val()},
             success:function(res){
                 if(res!=null)
                 {
                     //console.log(res);
                     //res 后台返回的token令牌
                     // key value
                     // 跨页面传值
                     var p2=localStorage.setItem("res",res);
                     console.log(p2+"这是p2的值");
                     location.href="Token2.html";
                 }
             }

         })
     })
 })
</script>
</html>

2、Index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>token验证后传递的值</title>
</head>
<body>
    <button type="button" id="btn">按下测试授权</button>
</body>
<script src="jquery-3.2.1.js"></script>
<script>
    var s2=localStorage.getItem("res");
    //显示一下Login页面传递的值 看看是否为空
    console.log(s2+"   这是页面2的token");
    $("#btn").click(function(){
        $.ajax({
            url:&#039;http://localhost:2108/api/Css/cs&#039;,
            type:&#039;get&#039;,
            beforeSend: function(request) {
                // 注意 basic后面有个空格 最好使用 &nbsp 空格符号
                // 设置请求头部 Authorization不区分大小写
              request.setRequestHeader("Authorization","basic "+ s2);
              },
            success:function(res){
                console.log(res+"res成功");
            }
        })
    })
</script>
</html>

3、后台

首先自己新建一个文件夹MyFite ,新建一个类,这个类就是验证当前用户的请求头信息是否正确,如果不正确则 false
using System;
using System.Linq;
using System.Web.Http; //引入命名空间
using System.Web.Http.Controllers;
using System.Threading;
using System.Security.Principal;
using WebAPI.Models;

namespace WebAPI.MyFile
{
    public class MyFilterAttribute: AuthorizeAttribute
    {
        MvcDemoEntities2 mvcdemo = new MvcDemoEntities2();
        protected override bool IsAuthorized(HttpActionContext actionContext)
        {
            //1、获取授权对象(请求头部中包含得Authrization对象)
            var auth = actionContext.Request.Headers.Authorization;
            if (auth != null)
            {
                //注意 前台的ajax设置请求头的时候basic后面一定要有空格或者用&nbsp来
                //不然Scheme会把token当作basic 
                if (auth.Scheme.ToLower() == "basic" && auth.Parameter != "")
                {
                    //认证的方式位basic认证,并且参数值不为空
                    //可以来进行验证你的令牌或者票据是否是正确的,如果正确返回true
                    //否则false
                    string token = auth.Parameter;
                    return CheckToken(token);
                }
                else
                {
                    return false;
                }
            }
            else
            {
                //为空 授权失败
                return false;
            }

        }

        public bool CheckToken(string token)
        {
            var rstoken = mvcdemo.Token.FirstOrDefault(x => x.token_text == token);
            if (rstoken != null)
            {
                //不为空,意味着查询到,但是不知道是否过期
                if (rstoken.token_time > DateTime.Now)
                {
                    //验证是否过了有效期 在有效期内
                    //还可以来进一步设置一个传递一个身份的id
                    //利用线程中的身份表示来存储用户信息(id)
                    Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(rstoken.usid.ToString()), null);
                    // 使用线程来获取当前用户id
                    //  Thread.CurrentPrincipal.Identity.Name;
                    return true;
                }
                else
                {

                    return false;
                }
            }
            else
            {
                //token错误
                return false;
            }

        }
    }
}

4、后台登录

        [Route("api/Userinfo/login")]
        [HttpPost]
        public IHttpActionResult UserInfo(UserInfo userInfo)
        {
            // 1、返回的密码 简单的密码加密
            var strNew = Md(userInfo.upwd);
            // 2、判断用户名和加密后的密码是否正确
            var useid = mvcdemo.UserInfo.FirstOrDefault(x=>x.uname==userInfo.uname && x.upwd== strNew).usid;
            var guid = "";
            Guid guid1 = Guid.NewGuid();
            guid = guid1.ToString().Replace("-", "");
            if (useid > 0)
            {
                 // 3、假设是第一次登录,Token表中没有令牌则生成第一次令牌
                var listtoken = mvcdemo.Token.FirstOrDefault(x => x.usid == useid);
                if (listtoken!=null)
                {
                    DeleteToken(useid); //如果存在则登录删除之前的Token
                    SaveChang(useid, guid);  // 保存用户和token
                }
                else
                {
                    SaveChang(useid, guid); //生成新的token保存
                }
            }
            return Ok(guid);  //返回一个token令牌到前台
        }
        /// <summary>
        /// 简单MD5加密密码方法
        /// </summary>
        /// <param name="strmd5">upwd参数</param>
        /// <returns>加密后的密码</returns>
        public string Md(string strmd5)
        {
            //创建md5
            MD5 md5 = MD5.Create();
            byte[] buffer = Encoding.GetEncoding("GBK").GetBytes(strmd5);
            byte[] md5buffer = md5.ComputeHash(buffer);
            string strNew = "";
            for (int i = 0; i < md5buffer.Length; i++)
            {
                strNew += md5buffer[i].ToString();
            }
            return strNew;
        }
        /// <summary>
        /// 添加token方法
        /// </summary>
        /// <param name="useid"></param>
        /// <param name="guid"></param>
        private void SaveChang(int useid, string guid)
        {
            mvcdemo.Token.Add(new Token
            {
                usid = useid,
                token_time = DateTime.Now.AddDays(1),
                token_text = guid,
                IsDel =true  //默认设置为true

            });
            mvcdemo.SaveChanges();
        }

        /// <summary>
        /// 如果登录成功删除之前的token
        /// </summary>
        /// <param name="useid"></param>
        public void DeleteToken(int useid)
        {
            var listtoken = mvcdemo.Token.FirstOrDefault(x => x.usid == useid);
            mvcdemo.Token.Remove(listtoken);
            mvcdemo.SaveChanges();
        }

5、这里测试一下是否可以授权

设置一个测试
        [Route("api/Css/cs")]
        [MyFilter] //加上刚才的写的MyFile
        [HttpGet]
        public IHttpActionResult Cs()
        {
            //线程获取当前用户id
            var a = Thread.CurrentPrincipal.Identity.Name;
            return Ok("授权到了"+ a.ToString());
        }

3、效果图

注意:这里请求的时候会产生跨域问题 所有我们要配置跨域,配置详情参考我之前发布的一篇关于WebApi 设置跨域问题 点击下面到达

地址:WebApi跨域问题

WebApi成功演示图