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认证、访问日志的更多相关文章

  1. ASP.NET WebApi 基于OAuth2.0实现Token签名认证

    一.课程介绍 明人不说暗话,跟着阿笨一起玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将是我们需要思考的问题.为了保护我们的WebApi数 ...

  2. ASP.NET WebApi 基于JWT实现Token签名认证

    一.前言 明人不说暗话,跟着阿笨一起玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将会是需要思考的问题.在ASP.NET WebServi ...

  3. ASP.NET WebApi 基于分布式Session方式实现Token签名认证

    一.课程介绍 明人不说暗话,跟着阿笨一起学玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将会是需要思考的问题.在ASP.NETWebSer ...

  4. ASP.NET WebApi 基于分布式Session方式实现Token签名认证(发布版)

    一.课程介绍 明人不说暗话,跟着阿笨一起学玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将会是需要思考的问题.在ASP.NETWebSer ...

  5. apache用户认证、域名跳转、Apache访问日志(两种格式)

    1.apache 设置,用户访问时 目录或文件的认证: 对目录的认证: <Directory /var/www/222> //指定认证的目录AllowOverride AuthConfig ...

  6. centos LAMP第二部分apache配置 下载discuz!配置第一个虚拟主机 安装Discuz! 用户认证 配置域名跳转 配置apache的访问日志 配置静态文件缓存 配置防盗链 访问控制 apache rewrite 配置开机启动apache tcpdump 第二十节课

    centos    LAMP第二部分apache配置  下载discuz!配置第一个虚拟主机 安装Discuz! 用户认证 配置域名跳转  配置apache的访问日志  配置静态文件缓存  配置防盗链 ...

  7. Apache用户认证、域名跳转、Apache访问日志

    5月29日任务 课程内容: 11.18 Apache用户认证11.19/11.20 域名跳转11.21 Apache访问日志扩展 apache虚拟主机开启php的短标签 http://ask.apel ...

  8. Linux CentOS7 VMware LAMP架构Apache用户认证、域名跳转、Apache访问日志

    一.Apache用户认证 vim /usr/local/apache2.4/conf/extra/httpd-vhosts.conf //把111.com那个虚拟主机编辑成如下内容 <Virtu ...

  9. C# WebApi 过滤器的使用开发接口必备利器

    在WEB Api中,引入了面向切面编程(AOP)的思想,在某些特定的位置可以插入特定的Filter进行过程拦截处理.引入了这一机制可以更好地践行DRY(Don’t Repeat Yourself)思想 ...

随机推荐

  1. 干货 | 10分钟带你全面掌握branch and bound(分支定界)算法-概念篇

    00 前言 之前一直做启发式算法,最近突然对精确算法感兴趣了.但是这玩意儿说实话是真的难,刚好boss又叫我学学column generation求解VRP相关的内容.一看里面有好多知识需要重新把握, ...

  2. Python3菜鸟教程笔记

    多行语句 同一行显示多条语句 Print 输出

  3. vscode快捷键,让你脱离鼠标,敲代码嗖嗖的

    蓝色为本人需要经常用到的,可忽略 vsCode软件相关 显示资源管理器:Ctrl + Shift + E 显示搜索: Ctrl + Shift + F 显示git:Ctrl + Shift + G 显 ...

  4. 刷题之给定一个整数数组 nums 和一个目标值 taget,请你在该数组中找出和为目标值的那 两个 整数

    今天下午,看了一会github,想刷个题呢,就翻出来了刷点题提高自己的实际中的解决问题的能力,在面试的过程中,我们发现,其实很多时候,面试官 给我们的题,其实也是有一定的随机性的,所以我们要多刷更多的 ...

  5. Spring Boot 面试,一个问题就干趴下了!(下)

    前些天栈长在Java技术栈微信公众号分享一篇文章:Spring Boot 面试,一个问题就干趴下了!,看到大家的留言很精彩,特别是说"约定大于配置"的这两个玩家. 哈哈,上墙的朋友 ...

  6. @PathVariable不起作用,报错:Cannot resolve @PathVariable ' '

    @PathVariable是占位符注解.可以把Url中变量的值传递到方法参数中. 示例如下: @PostMapping("/user/name/{id}") @ResponseBo ...

  7. tomcat启动报错java.lang.OutOfMemoryError:PermGen space解决办法

    tomcat启动错误提示: 严重: Error waiting for multi-thread deployment of WAR files to completejava.util.concur ...

  8. 团队作业-Beta版本演示

    组长博客链接 https://www.cnblogs.com/cmlei/p/12063671.html 本组成员 031702431 陈明磊 组长 031702227 林镕炜 031702413 韩 ...

  9. DELPHI7 ADO二层升三层新增LINUX服务器方案

    DELPHI7 ADO二层升三层新增LINUX服务器方案 引子:笔者曾经无数次在用户的LINUX服务器上创建一个WINDOWS虚拟机,用于运行自己DELPHI开发中间件. 现在再不需要如此麻烦了. 咏 ...

  10. C++多线程下出现内存越界问题总结

    工作中遇到这样一个问题,某个多级流水多线程的程序,在压力测试下会偶现segmentation fault11错误,错误出现在运行类函数的地方,而后排查后发现是由于多线程争抢导致类被析构后才走入判断,导 ...