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="width: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>
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤