c# webapi 过滤器token、sign认证、访问日志
1、token认证
服务端登录成功后分配token字符串。记录缓存服务器,可设置有效期
var token = Guid.NewGuid().ToString().Replace("-", "");
var expire = DateTime.Now.AddHours();
var timespan = ( expire- DateTime.Now);
var key = string.Format("login-{0}", apiRm.Result.UserID);
RedisCacheHelper.SetCacheByKey<string>(key, JsonHelper.ToJson(apiRm.Result), timespan);
通过header传入token后进行服务端认证有效性
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' --header 'token: 1000-e0622f06a9a842a5b79a5295e6d4b235' -d
在controller或action可设置属性是否要验证token
controller:[RoutePrefix("api/Out"), OperateTrack, AuthToken(AuthTypeEnum.Driver)]
或
action:[HttpPost, Route("GetOutInfo"),AuthToken(AuthTypeEnum.Driver)] 读取过滤器传过来的信息:
var user = ControllerContext.RouteData.Values["user"];
var user1 = HttpContext.Current.User;
创建AuthTokenAttribute继承AuthorizeAttribute
public class AuthTokenAttribute : AuthorizeAttribute
{
public AuthTypeEnum VerifyAuth { get; set; } public AuthTokenAttribute() { this.VerifyAuth = AuthTypeEnum.Common; } public AuthTokenAttribute(AuthTypeEnum verifyAuth)
{
this.VerifyAuth = verifyAuth;
} protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
{
var request = actionContext.Request;
if(VerifyAuth== AuthTypeEnum.Driver)
{
var rm= AuthDriver(actionContext);
if (!rm.IsSuccess)
return false;
}
return true;
}
protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
{
StringBuilder sbMsg = new StringBuilder();
if (VerifyAuth == AuthTypeEnum.Driver)
{
var rm = AuthDriver(actionContext);
if (!rm.IsSuccess)
sbMsg.Append(rm.Message);
}
var content = JsonConvert.SerializeObject(new ResultApiModel { IsSuccess = false, Message = sbMsg.ToString() + ",验证失败,状态:" + (int)HttpStatusCode.Unauthorized, Code = ((int)HttpStatusCode.Unauthorized).ToString() });
actionContext.Response = new HttpResponseMessage
{
Content = new StringContent(content, Encoding.UTF8, "application/json"),
StatusCode = HttpStatusCode.Unauthorized
};
} private ResultApiModel AuthDriver(System.Web.Http.Controllers.HttpActionContext actionContext)
{
//todo 验证token
//向action传值,在action中可以使用:var user = ControllerContext.RouteData.Values["user"];获取到
actionContext.ControllerContext.RouteData.Values["user"] = v;
SetPrincipal(new UserPrincipal<int>(tokenV));
return ResultApiModel.Create(true);
}
public static void SetPrincipal(IPrincipal principal)
{
Thread.CurrentPrincipal = principal;
//每次都重新覆盖user,避免不同用户对不同action的访问
if (HttpContext.Current != null)
{
HttpContext.Current.User = principal;
}
}
}
public enum AuthTypeEnum
{
Common=,
Driver=
} IPrincipal:
public class UserIdentity<TKey> : IIdentity
{
public UserIdentity(IUser<TKey> user)
{
if (user != null)
{
IsAuthenticated = true;
UserID = user.UserID;
LoginNo = user.LoginNo.ToString();
Name = user.LoginNo.ToString();
UserName = user.UserName;
RoleCode = user.RoleCode;
token = user.token;
}
} public string AuthenticationType
{
get { return "CustomAuthentication"; }
} public TKey UserID { get; private set; } public bool IsAuthenticated { get; private set; } public string LoginNo { get; private set; } public string Name { get; private set; } public string UserName { get; private set; } public string RoleCode { get; private set; } public string token { get; private set; }
} public class UserPrincipal<TKey> : IPrincipal
{
public UserPrincipal(UserIdentity<TKey> identity)
{
Identity = identity;
} public UserPrincipal(IUser<TKey> user)
: this(new UserIdentity<TKey>(user))
{ } /// <summary>
///
/// </summary>
public UserIdentity<TKey> Identity { get; private set; } IIdentity IPrincipal.Identity
{
get { return Identity; }
} bool IPrincipal.IsInRole(string role)
{
throw new NotImplementedException();
}
} public interface IUser<T>
{
/// <summary>
/// 用户id
/// </summary>
T UserID { get; set; } /// <summary>
/// 登录账号
/// </summary>
string LoginNo { get; set; }
/// <summary>
/// 用户名称
/// </summary>
string UserName { get; set; }
/// <summary>
/// 角色编号
/// </summary>
string RoleCode { get; set; } /// <summary>
/// 登录后分配token
/// </summary>
string token { get; set; }
}
2、验证签名:
约定签名规则
controller或action增加属性验证
[AuthSign(AuthSignTypeEnum.Common)]
创建AuthSignAttribute继承AuthorizeAttribute
public class AuthSignAttribute : AuthorizeAttribute
{
public AuthSignTypeEnum AuthSignType { get; set; }
public AuthSignAttribute() { this.AuthSignType = AuthSignTypeEnum.Common; }
public AuthSignAttribute(AuthSignTypeEnum authSignType)
{
this.AuthSignType = authSignType;
}
/// <summary>
/// 公共请求主体数据
/// </summary>
private string CommonRequestBodyData { get; set; } /// <summary>
/// 权限验证
/// </summary>
/// <param name="actionContext"></param>
/// <returns></returns>
protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
{
var request = actionContext.Request;
var requestBodyData = StreamHelper.GetStream2String(request.Content.ReadAsStreamAsync().Result);
if (AuthSignType == AuthSignTypeEnum.Common)
{
CommonRequestBodyData = requestBodyData.TrimStart("data=".ToCharArray());
var urlParam = GetUrlParam(actionContext);
if (!urlParam.IsSuccess) return false;
var rm = AuthSignCommon(urlParam.Result, CommonRequestBodyData);
if (!rm.IsSuccess)
return false;
} return true;
} private ResultApiModel AuthSignCommon(CommonRequestApiModel request, string requestBodyData)
{
//todo 验证signreturn ResultApiModel.Create(true);
}/// <summary>
/// 处理未授权的请求
/// </summary>
/// <param name="actionContext"></param>
protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
{
StringBuilder sbMsg = new StringBuilder();
if (AuthSignType == AuthSignTypeEnum.Common)
{
//todo 处理验证失败信息
}
var content = JsonConvert.SerializeObject(new ResultApiModel { IsSuccess = false, Message = sbMsg.ToString() + " 签名验证失败,状态:" + HttpStatusCode.Unauthorized });
actionContext.Response = new HttpResponseMessage
{
Content = new StringContent(content, Encoding.UTF8, "application/json"),
StatusCode = HttpStatusCode.Unauthorized
};
}
}
/// <summary>
/// 签名类型
/// </summary>
public enum AuthSignTypeEnum
{
Common =
}
3、访问日志:
controller或action增加属性
[RoutePrefix("api/Out"), OperateTrack, AuthToken(AuthTypeEnum.Driver)]
不需要日志可以[NoLog]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true)]
public class NoLogAttribute : Attribute
{
}
继承:ActionFilterAttribute
public class OperateTrackAttribute : ActionFilterAttribute
{
/// <summary>
/// 自定义参数
/// </summary>
public string msg { get; set; }
public OperateTrackAttribute()
{ } /// <summary>
/// 初始化时填入类的说明
/// </summary>
/// <param name="message"></param>
public OperateTrackAttribute(string message)
{
msg = message;
} private static readonly string key = "enterTime";
public override Task OnActionExecutingAsync(System.Web.Http.Controllers.HttpActionContext actionContext, CancellationToken cancellationToken)
{
if (SkipLogging(actionContext))
{
return base.OnActionExecutingAsync(actionContext, cancellationToken); }
//记录进入请求的时间
actionContext.Request.Properties[key] = DateTime.Now.ToBinary(); return base.OnActionExecutingAsync(actionContext, cancellationToken);
}
/// <summary>
/// 在请求执行完后 记录请求的数据以及返回数据
/// </summary>
/// <param name="actionExecutedContext"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public override Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
{
object beginTime = null;
if (actionExecutedContext.Request.Properties.TryGetValue(key, out beginTime))
{
DateTime time = DateTime.FromBinary(Convert.ToInt64(beginTime));
HttpRequest request = HttpContext.Current.Request;
string token = request.Headers["token"]; WebApiActionLogModel apiActionLog = new WebApiActionLogModel
{
Id = Guid.NewGuid(),
//获取action名称
actionName = actionExecutedContext.ActionContext.ActionDescriptor.ActionName,
//获取Controller 名称
controllerName = actionExecutedContext.ActionContext.ActionDescriptor.ControllerDescriptor.ControllerName,
//获取action开始执行的时间
enterTime = time,
//获取执行action的耗时
costTime = (DateTime.Now - time).TotalMilliseconds,
navigator = request.UserAgent,
token = token,
//获取用户token
userId = getUserByToken(token),
//获取访问的ip
ip = request.UserHostAddress,
userHostName = request.UserHostName,
urlReferrer = request.UrlReferrer != null ? request.UrlReferrer.AbsoluteUri : "",
browser = request.Browser.Browser + " - " + request.Browser.Version + " - " + request.Browser.Type,
//获取request提交的参数
paramaters = StreamHelper.GetStream2String(actionExecutedContext.Request.Content.ReadAsStreamAsync().Result),
//获取response响应的结果
executeResult = StreamHelper.GetStream2String(actionExecutedContext.Response.Content.ReadAsStreamAsync().Result),
comments = msg,
RequestUri = request.Url.AbsoluteUri
};
//记debug
Log.DefaultLogDebug(string.Format("actionExecutedContext {0} 请求:{1}", apiActionLog.controllerName + "/" + apiActionLog.actionName, JsonHelper.ToJson(apiActionLog)));
}
return base.OnActionExecutedAsync(actionExecutedContext, cancellationToken); }
/// <summary>
/// 获取当前登录用户的id
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
public static string getUserByToken(string token)
{
UserIdentity<int> u = HttpContext.Current.User.Identity as UserIdentity<int>;
if (u == null) return "未登录用户" + token;
return u.LoginNo.ToString();
} /// <summary>
/// 判断类和方法头上的特性是否要进行Action拦截
/// </summary>
/// <param name="actionContext"></param>
/// <returns></returns>
private static bool SkipLogging(System.Web.Http.Controllers.HttpActionContext actionContext)
{
return actionContext.ActionDescriptor.GetCustomAttributes<NoLogAttribute>().Any() || actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<NoLogAttribute>().Any();
}
}
c# webapi 过滤器token、sign认证、访问日志的更多相关文章
- ASP.NET WebApi 基于OAuth2.0实现Token签名认证
一.课程介绍 明人不说暗话,跟着阿笨一起玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将是我们需要思考的问题.为了保护我们的WebApi数 ...
- ASP.NET WebApi 基于JWT实现Token签名认证
一.前言 明人不说暗话,跟着阿笨一起玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将会是需要思考的问题.在ASP.NET WebServi ...
- ASP.NET WebApi 基于分布式Session方式实现Token签名认证
一.课程介绍 明人不说暗话,跟着阿笨一起学玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将会是需要思考的问题.在ASP.NETWebSer ...
- ASP.NET WebApi 基于分布式Session方式实现Token签名认证(发布版)
一.课程介绍 明人不说暗话,跟着阿笨一起学玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将会是需要思考的问题.在ASP.NETWebSer ...
- apache用户认证、域名跳转、Apache访问日志(两种格式)
1.apache 设置,用户访问时 目录或文件的认证: 对目录的认证: <Directory /var/www/222> //指定认证的目录AllowOverride AuthConfig ...
- centos LAMP第二部分apache配置 下载discuz!配置第一个虚拟主机 安装Discuz! 用户认证 配置域名跳转 配置apache的访问日志 配置静态文件缓存 配置防盗链 访问控制 apache rewrite 配置开机启动apache tcpdump 第二十节课
centos LAMP第二部分apache配置 下载discuz!配置第一个虚拟主机 安装Discuz! 用户认证 配置域名跳转 配置apache的访问日志 配置静态文件缓存 配置防盗链 ...
- Apache用户认证、域名跳转、Apache访问日志
5月29日任务 课程内容: 11.18 Apache用户认证11.19/11.20 域名跳转11.21 Apache访问日志扩展 apache虚拟主机开启php的短标签 http://ask.apel ...
- Linux CentOS7 VMware LAMP架构Apache用户认证、域名跳转、Apache访问日志
一.Apache用户认证 vim /usr/local/apache2.4/conf/extra/httpd-vhosts.conf //把111.com那个虚拟主机编辑成如下内容 <Virtu ...
- C# WebApi 过滤器的使用开发接口必备利器
在WEB Api中,引入了面向切面编程(AOP)的思想,在某些特定的位置可以插入特定的Filter进行过程拦截处理.引入了这一机制可以更好地践行DRY(Don’t Repeat Yourself)思想 ...
随机推荐
- 机器学习---三种线性算法的比较(线性回归,感知机,逻辑回归)(Machine Learning Linear Regression Perceptron Logistic Regression Comparison)
最小二乘线性回归,感知机,逻辑回归的比较: 最小二乘线性回归 Least Squares Linear Regression 感知机 Perceptron 二分类逻辑回归 Binary Logis ...
- 63、Spark Streaming:架构原理深度剖析
一.架构原理深度剖析 StreamingContext初始化时,会创建一些内部的关键组件,DStreamGraph,ReceiverTracker,JobGenerator,JobScheduler, ...
- sublime text 3插件改造之添加从模版新增文件到指定目录
简介:以前使用ST2里面的Sublime NFFT插件比较顺手,最近安装了ST3,但是Sublime NFFT插件不支持ST3,就下载了SublimeTmpl从模版新建文件插件.在使用时,习惯在侧边栏 ...
- 玩家属性同步优化-脏数据标记(位运算、数组、stl之bitset)
把大神的帖子中一部分摘抄出来,结合自己写的位运算代码和循环代码(数组遍历)进行性能测试分析并给出结果. 摘自: https://www.gameres.com/827195.html 本文适用于所有脏 ...
- 最近公司遇到了APR攻击,顺便了解一下知识
原因及背景 最近公司遇到了APR攻击导致整个公司研发部.测试部.客服部.工程部等几个部门统一无法上网,TV(team viewer)无法使用,部署在公网的B/S架构系统系统无法访问,开发代码上传和下载 ...
- automapper 源中有多个属性类映射到同一个 目标中
CreateMap<TempBranchActivity, BranchActivityOutput>() .ConstructUsing((src, ctx) => ctx.Map ...
- NoSql数据库Redis系列(5)——Redis主从复制
前面介绍Redis,我们都在一台服务器上进行操作的,也就是说读和写以及备份操作都是在一台Redis服务器上进行的,那么随着项目访问量的增加,对Redis服务器的操作也越加频繁,虽然Redis读写速度都 ...
- idea在docker环境,调试spring boot程序
允许docker被远程访问 见:https://www.cnblogs.com/wintersoft/p/10921396.html 教程见:https://spring.io/guides/gs/s ...
- 对异步处理的http接口进行性能测试
以前对接口做性能测试,接口都是同步处理的,请求之后等待响应结果就知道处理结果了,这样只要看这个接口是否异常,如果无异常无报错记录这个接口的响应时间.TPS等性能指标进行分析就可以了,最近在工作中遇到了 ...
- android -------- AES加密解密算法
AES加密标准又称为高级加密标准Rijndael加密法,是美国国家标准技术研究所NIST旨在取代DES的21世纪的加密标准.AES的基本要求是,采用对称分组密码体制,密钥长度可以为128.192或25 ...