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)思想 ...
随机推荐
- 【18NOIP普及组】对称二叉树(信息学奥赛一本通 1981)(洛谷 5018)
[题目描述] 一棵有点权的有根树如果满足以下条件,则被轩轩称为对称二叉树: 1.二叉树: 2.将这棵树所有节点的左右子树交换,新树和原树对应位置的结构相同且点权相等. 下图中节点内的数字为权值,节点外 ...
- Spring Cloud Gateway(十一):全局过滤器GlobalFilter
本文基于 spring cloud gateway 2.0.1 1.简介 GlobalGilter 全局过滤器接口与 GatewayFilter 网关过滤器接口具有相同的方法定义.全局过滤器是一系列特 ...
- Stringbuilde方法的用法以及其作用
Stringbuilde的方法有以下几种(常用的):(java中的语法) 在程序开发过程中,我们常常碰到字符串连接的情况,方便和直接的方式是通过"+"符号来实现,但是这种方式达到目 ...
- redis状态详解
redis查看状态信息 info all|default Info 指定项 server服务器信息 redis_version : Redis 服务器版本 redis_git_sha1 : Git S ...
- 【转】Android ROM分析(1):刷机原理及方法
一.刷机原理 android系统启动的时候,首先会进行一些诸如硬件自检之类的操作,这些操作完成以后(至少它应该知道当前的机器有没有电),会检查一下当前手机按键的状态(接下来就是所谓刷机模式切换了,不同 ...
- 已知X,Y独立,那么X^2与Y也独立
考虑离散情况, P{X^2=k} => P{X=sqrt(k)} 由X,Y独立可知, P{X=Sqrt(k} | Y=y} =P{X=Sqrt(x)}, P{X^2=k | Y=y} =P{ ...
- np.stack
- 解决VS Code开发Python3语言自动补全功能
1.打开设置界面 2)使用快捷键组合[Ctrl+Shift+p] . 输入setting,选中首选项的user setting模式设置界面 在打开的User Settings文件界面,搜索:pytho ...
- libpng error: IHDR: CRC error
原本正常显示在主页端logo图片无法显示了,爆出如下错误: libpng error: IHDR: CRC error 查找原因如下:
- Java通过行为参数化传递代码
在软件工程中,一个众所周知的问题就是,不管做什么,用户的需求肯定会变.如何应对这样不断变化的需求?理想的状态下,应该把的工作量降到最少.此外,类似的新功能实现起来还应该很简单,而且易于长期维护.行为参 ...