c# 自定义验证登录(Authorize)

我们的项目本来是用azure的auth认证,是用过程中发现登录速度太慢了,所以还是自己搞一个吧,没想到搞起来挺简单的,不是用一个专门的认证服务器哈,就是一个简单的工具类。

验证是否登录的类

    /// <summary>
    /// 认证类继承
    /// </summary>
    public class RequestAuthorizeAttribute : AuthorizeAttribute
    {
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            // 是否不需要验证 或者 已经登录
            if (SkipAuthorization(actionContext) || IsLogin(actionContext))
                return;

            actionContext.Response = GetResponse();
        }

        /// <summary>
        /// 返回信息接口
        /// </summary>
        private HttpResponseMessage GetResponse()
        {
            var response = ServiceResponse<bool>.WarningResponse(401, CommonConst.Msg_NoLogin, false);
            return JsonHelper.ToHttpResponseMessage(response);
        }

        /// <summary>
        /// 判断是否匿名使用接口
        /// </summary>
        private static bool SkipAuthorization(HttpActionContext actionContext)
        {
            if (!actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any<AllowAnonymousAttribute>())
                return actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any<AllowAnonymousAttribute>();
            return true;
        }

        /// <summary>
        /// 是否已经登录
        /// </summary>
        private bool IsLogin(HttpActionContext actionContext)
        {
            var authorization = Guid.Empty.ToString(); // MD5值
            if (actionContext.Request.Headers.Authorization != null)
            {
                authorization = actionContext.Request.Headers.Authorization.ToString();
            }

            var user = OperatorProvider.Provider.GetCurrent(authorization);
            return user != null;
        }
    }

获取header值:

参考资料:获取header

代码如下:

        private bool IsLogin(HttpActionContext actionContext)
        {
            var token = Guid.Empty.ToString(); // MD5值
            var openId = string.Empty; // MD5值

            actionContext.Request.Headers.TryGetValues("Token", out var tokens);
            actionContext.Request.Headers.TryGetValues("OpenId", out var openIds);
            if (tokens.IsNotNull() && tokens.Any() && openIds.IsNotNull() && openIds.Any())
            {
                token = tokens.FirstOrDefault();
                openId = openIds.FirstOrDefault();

                var cache = CacheHelper.GetCache(token);
                if (cache.IsNotNull())//如果缓存中存在该token对应的值,说明已经登录了
                    return true;

                //获取用户
                var strUserUrl = HttpUtility.UrlDecode(ConfigurationManager.AppSettings["sso_req_user_url"]);

                var reqUserUrl = string.Format(strUserUrl, openId, token);
                var reqUser = WebRequest.Create(reqUserUrl) as HttpWebRequest;
                reqUser.Method = "get";
                reqUser.ContentType = "application/json";
                var resUser = reqUser.GetResponse() as HttpWebResponse;
                //以流的形式读取,返回的就是字符串的json格式
                StreamReader readerUser = new StreamReader(resUser.GetResponseStream());
                var resUserData = readerUser.ReadToEnd();
                if (resUser.StatusCode == HttpStatusCode.OK)
                {
                    var suser = JsonConvert.DeserializeObject<SSOUser>(resUserData);
                    var userId = Guid.Parse(suser.OpenId);
                    CacheHelper.SetCache(token, userId);
                    return true;
                }
                else
                {
                    return false;
                }
            }
            return false;
        }

使用

登录接口数据缓存处理,获取到用户信息后,生成guid作为token,每次登录都会重新生成token,返回给请求来源,web端只保存token值即可,每次请求的时候把token放到header里面。

BaseApiController处理,获取header里面的token值,把用户信息放到缓存里面,从缓存中获取后放到基类里面的model中,子类都可以使用用户信息。

    [RequestAuthorize]
    public class BaseApiController : ApiController
    {

        /// <summary>
        /// 当前用户信息实体
        /// </summary>
        public OperatorModel CurrentUserModel
        {
            get
            {
                var values = HttpContext.Current.Request.Headers.GetValues("authorization");
                var authorization=Guid.Empty.ToString();
                if (values != null && values.Length > 0)
                    authorization = values[0];
                var currentUserModel = OperatorProvider.Provider.GetCurrent(authorization);
                if (currentUserModel == null)
                {
                    currentUserModel = new OperatorModel { LoginName = "admin" };
                }
                return currentUserModel;
            }
        }
    }

 web端使用token(VUE)

token帮助类

import Cookies from 'js-cookie'

const TokenKey = 'hs_t'

export function getToken() {
  return Cookies.get(TokenKey)
}

export function setToken(token) {
  return Cookies.set(TokenKey, token)
}

export function removeToken() {
  return Cookies.remove(TokenKey)
}

login.vue

<template>
  <div class="login-container">
    <el-form ref="model" :model="model" :rules="loginRules" class="login-form" autocomplete="on" label-position="left">
      <div class="title-container">
        <h3 class="title">教师中心</h3>
      </div>

      <el-form-item prop="LoginName">
        <span class="svg-container">
          <svg-icon icon-class="user" />
        </span>
        <el-input ref="LoginName" v-model="model.LoginName" placeholder="登录名" name="LoginName" type="text" tabindex="1"
          autocomplete="on" />
      </el-form-item>

      <el-tooltip v-model="capsTooltip" content="Caps lock is On" placement="right" manual>
        <el-form-item prop="password">
          <span class="svg-container">
            <svg-icon icon-class="password" />
          </span>
          <el-input :key="passwordType" ref="password" v-model="model.password" :type="passwordType" placeholder="密码"
            name="password" tabindex="2" autocomplete="on" @keyup.enter.native="login" />
          <span class="show-pwd" @click="showPwd">
            <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
          </span>
        </el-form-item>
      </el-tooltip>

      <el-button :loading="loading" type="primary" style="100%;margin-bottom:30px;" @click.native.prevent="login">
        登录</el-button>
    </el-form>
  </div>
</template>
<script>
  import { deepClone } from "@/utils";
  import { setToken, getToken } from '@/utils/auth'
  import { login } from "@/api/user";

  const defaulModel = {
    LoginName: "",
    password: "",
    orgCode: "",
    phone: "",
    UserType: "Teacher"
  };

  export default {
    name: 'Login',
    data() {

      return {
        model: deepClone(defaulModel),
        loginForm: {
          username: 'admin',
          password: '111111'
        },
        loginRules: {
          LoginName: [
            { required: true, message: "请输入登录名", trigger: 'blur' }
          ],
          password: [
            { required: true, message: "请输入密码", trigger: 'blur' }
          ]
        },
        passwordType: 'password',
        capsTooltip: false,
        loading: false,
        showDialog: false,
        redirect: undefined,
        otherQuery: {}
      }
    },
    created() {
      // window.addEventListener('storage', this.afterQRScan)
    },
    methods: {
      showPwd() {
        if (this.passwordType === 'password') {
          this.passwordType = ''
        } else {
          this.passwordType = 'password'
        }
        this.$nextTick(() => {
          this.$refs.password.focus()
        })
      },
      async login() {
        var v = true;
        this.$refs.model.validate(valid => {
          v = valid;
        });
        if (!v) {
          //验证不通过
          return false;
        }
        var res = await login(this.model)
        console.log(res)
        if (res.code == 200) {
          setToken(res.data)
          this.$router.push("/");
        }
      }
    }
  }
</script>
原文地址:https://www.cnblogs.com/dawenyang/p/11272534.html