近些天,看了一些博客园大牛关于webApi项目的的文章,也有请教师兄一些问题,自己做了个Demo试了试,收获甚多。感谢感谢,下面是我一些学习的总结,如若有错的地方请多多指教!!

WebApi登陆与身份验证

因为在调用接口的时候都必须传sessionKey参数过去,所以必须先登录验证身份。

如果是已注册用户则账号登陆,获得其身份标识的 sessionkey,如果是非账户用户则可以匿名登陆,要输入用户IP地址或者和客户端设备号等以获得sessionkey,然后可以去注册。

 

#region  登录API
/// <summary>
/// 登录API (账号登陆)
/// </summary>
/// <param name="phone">登录帐号手机号</param>
/// <param name="hashedPassword">加密后的密码,这里避免明文,客户端加密后传到API端</param>
/// <param name="deviceType">客户端的设备类型</param>
/// <param name="clientId">客户端识别号, 一般在APP上会有一个客户端识别号</param>
/// <returns></returns>
[Route("account/login")]
public SessionObject Login(string phone, string hashedPassword, int deviceType = , string clientId = "") {
if (string.IsNullOrEmpty(phone))
throw new ApiException("用户名不能为空。", "RequireParameter_userphone");
if (string.IsNullOrEmpty(hashedPassword))
throw new ApiException("hashedPassword 不能为空.", "RequireParameter_hashedPassword"); int timeout = ; var nowUser = _authenticationService.GetUserByPhone(phone);
if (nowUser == null)
throw new ApiException("帐户不存在", "Account_NotExits"); #region 验证密码
if (!string.Equals(nowUser.Password, hashedPassword)) {
throw new ApiException("错误的密码", "Account_WrongPassword");
}
#endregion if (!nowUser.IsActive)
throw new ApiException("用户处于非活动状态.", "InactiveUser"); UserDevice existsDevice = _authenticationService.GetUserDevice(nowUser.UserId, deviceType); if (existsDevice == null) {
string passkey = MD5CryptoProvider.GetMD5Hash(nowUser.UserId + nowUser.Phone + DateTime.UtcNow+ Guid.NewGuid());
existsDevice = new UserDevice() {
UserId = nowUser.UserId,
CreateTime = DateTime.UtcNow,
ActiveTime = DateTime.UtcNow,
ExpiredTime = DateTime.UtcNow.AddMinutes(timeout),
DeviceType = deviceType,
SessionKey = passkey
};
_authenticationService.AddUserDevice(existsDevice);
}
else {
existsDevice.ActiveTime = DateTime.UtcNow;
existsDevice.ExpiredTime = DateTime.UtcNow.AddMinutes(timeout);
_authenticationService.UpdateUserDevice(existsDevice);
}
nowUser.Password = "";
return new SessionObject() { SessionKey = existsDevice.SessionKey, LogonUser = nowUser };
}
#endregion

登录API

        #region 匿名登陆
/// <summary>
/// 匿名登陆
/// </summary>
/// <param name="ip">用户ip地址</param>
/// <param name="deviceType">设备类型</param>
/// <param name="clientId">客户端识别号</param>
/// <returns></returns>
[Route("account/AnonymousLogin")]
public SessionObject1 AnonymousLogin(string ip, int deviceType = , string clientId = "")
{
if (string.IsNullOrEmpty(ip))throw new ApiException("ip地址不能为空。", "RequireParameter_ip"); int timeout = ; UserDevice existsDevice = _authenticationService.GetUserDevice(ip, deviceType);
// Session.QueryOver<UserDevice>().Where(x => x.AccountId == nowAccount.Id && x.DeviceType == deviceType).SingleOrDefault();
if (existsDevice == null) {
string passkey = MD5CryptoProvider.GetMD5Hash(ip+DateTime.UtcNow + Guid.NewGuid());
existsDevice = new UserDevice() {
IP = ip,
CreateTime = DateTime.UtcNow,
ActiveTime = DateTime.UtcNow,
ExpiredTime = DateTime.UtcNow.AddMinutes(timeout),
DeviceType = deviceType,
SessionKey = passkey
};
_authenticationService.AddUserDevice(existsDevice);
}
else {
existsDevice.ActiveTime = DateTime.UtcNow;
existsDevice.ExpiredTime = DateTime.UtcNow.AddMinutes(timeout);
_authenticationService.UpdateUserDevice(existsDevice);
}
return new SessionObject1() { SessionKey = existsDevice.SessionKey, Ip=ip };
} #endregion

匿名登陆

身份信息的认证是通过Web API 的 ActionFilter来实现的,所有需要身份验证的API请求都会要求客户端传一个SessionKey。

在这里我们通过一个自定义的SessionValidateAttribute来做客户端的身份验证, 其继承自 System.Web.Http.Filters.ActionFilterAttribute。

    public class SessionValidateAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
public const string SessionKeyName = "SessionKey";
public const string LogonUserName = "LogonUser"; public override void OnActionExecuting(HttpActionContext filterContext)
{
var qs = HttpUtility.ParseQueryString(filterContext.Request.RequestUri.Query);
string sessionKey = qs[SessionKeyName]; if (string.IsNullOrEmpty(sessionKey))
{
throw new ApiException("无效 Session.", "InvalidSession");
} IAuthenticationService authenticationService = new AuthenticationService();//IocManager.Intance.Reslove<IAuthenticationService>(); //验证用户session
var userSession = authenticationService.GetUserDevice(sessionKey); if (userSession == null)
{
throw new ApiException("无此 sessionKey", "RequireParameter_sessionKey");
}
else
{
//todo: 加Session是否过期的判断
if (userSession.ExpiredTime < DateTime.UtcNow)
throw new ApiException("session已过期", "SessionTimeOut"); var logonUser = authenticationService.GetUser(userSession.UserId);
if (logonUser != null)
{
filterContext.ControllerContext.RouteData.Values[LogonUserName] = logonUser;
SetPrincipal(new UserPrincipal<int>(logonUser));
}
userSession.ActiveTime = DateTime.UtcNow;
userSession.ExpiredTime = DateTime.UtcNow.AddMinutes();
authenticationService.UpdateUserDevice(userSession);
}
} public static void SetPrincipal(IPrincipal principal)
{
Thread.CurrentPrincipal = principal;
if (HttpContext.Current != null)
{
HttpContext.Current.User = principal;
}
}
}

API身份验证

需要身份验证的apiControler 上加上[sessionValidate],则这个Controller下面所有Action都将拥有身份验证功能

如果是需要管理员权限才能请求的数据的话,那么我们再定义一个 SessionValidateAdminAttribute 来做管理员的身份验证,在需要管理员权限才能请求的控制器上加上[SessionValidateAdminAttribute ],则这个控制器下面所有Action都只有通过身份验证的管理员才有权限请求。

public class SessionValidateAdminAttribute : System.Web.Http.Filters.ActionFilterAttribute {
public const string SessionKeyName = "SessionKey";
public const string LogonUserName = "LogonUser"; public override void OnActionExecuting(HttpActionContext filterContext) {
var qs = HttpUtility.ParseQueryString(filterContext.Request.RequestUri.Query);
string sessionKey = qs[SessionKeyName]; if (string.IsNullOrEmpty(sessionKey)) {
throw new ApiException("无效 Session.", "InvalidSession");
} IAuthenticationService authenticationService = new AuthenticationService();//IocManager.Intance.Reslove<IAuthenticationService>(); //验证用户session
var userSession = authenticationService.GetUserDevice(sessionKey); if (userSession == null) {
throw new ApiException("无此 sessionKey", "RequireParameter_sessionKey");
}
else {
//todo: 加Session是否过期的判断
if (userSession.ExpiredTime < DateTime.UtcNow)
throw new ApiException("session已过期", "SessionTimeOut"); var logonUser = authenticationService.GetUser(userSession.UserId); if (logonUser == null) {
throw new ApiException("无此用户", "Invalid_User");
}
else
{
if (logonUser.Permissions == )
{
filterContext.ControllerContext.RouteData.Values[LogonUserName] = logonUser;
SessionValidateAttribute.SetPrincipal(new UserPrincipal<int>(logonUser));
}
else
{
throw new ApiException("用户无权限", "No permissions");
}
}
userSession.ActiveTime = DateTime.UtcNow;
userSession.ExpiredTime = DateTime.UtcNow.AddMinutes();
authenticationService.UpdateUserDevice(userSession);
}
} }

SessionValidateAdminAttribute

关于:[EnableCors(origins: "*", headers: "*", methods: "*")] 的说明,

详情查看:http://www.cnblogs.com/artech/p/cors-4-asp-net-web-api-05.html

关于用户过期时间:每次调用接口的时候 会自动更新sessionKey的过期时间,如果长时间未更新,则下次访问时会过期,则需要重新登陆。

加入身份验证后的 UserControler

[EnableCors(origins: "*", headers: "*", methods: "*")]
[RoutePrefix("api/Users"), SessionValidate, WebApiTracker]
public class UsersController : ApiController
{
private readonly IUsers _users=new UsersImpl();
#region 根据用户ID获得用户信息
/// <summary>
/// 根据用户ID获得用户信息(获得数据)
/// </summary>
/// <param name="sessionKey">sessionKey</param>
/// <param name="id">用户id</param>
/// <returns>result</returns>
public ApiResult<Users> GetUserById( string sessionKey,int id)
{
Users modelUsers = _users.GetUserByUsersId(id);
if (modelUsers != null)
{
return new ApiResult<Users>("","获取用户信息成功",modelUsers);
}
else return new ApiResult<Users>("","无此用户信息",null);
}
#endregion /// <summary>
/// 新用户注册(增加数据)
/// </summary>
/// <param name="modelUsers"></param>
/// <returns>result</returns>
[HttpPost, Route("api/UserRegistration")]
public ApiResult<bool> UserRegistration(string sessionKey, AddUserRq modelUsers)
{
Users usersModel=new Users();
usersModel.IsActive = true;
usersModel.Password = modelUsers.Password;
usersModel.Permissions = ;
usersModel.Phone = modelUsers.Phone;
usersModel.Sex = modelUsers.Sex;
usersModel.TrueName = modelUsers.TrueName;
usersModel.UserName = modelUsers.UserName;
return _users.RegistrationNewUsers(usersModel);
}
}

UsersControllers

此随笔乃本人学习工作记录,如有疑问欢迎在下面评论,转载请标明出处。

如果对您有帮助请动动鼠标右下方给我来个赞,您的支持是我最大的动力。

2017-11 代码及数据库文件已经上传至 https://github.com/huangenai/WebAPI

学习总结之 WebApi 用户登录和匿名登录,及权限验证的更多相关文章

  1. WebApi用户登录验证及服务器端用户状态存取

    最近项目需要给手机端提供数据,采用WebApi的方式,之前的权限验证设计不是很好,这次采用的是Basic基础认证. 1.常见的认证方式 我们知道,asp.net的认证机制有很多种.对于WebApi也不 ...

  2. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(15)-用户登录详细错误和权限数据库模型设计

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(15)-用户登录详细错误和权限数据库模型设计     ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)    ...

  3. Spring MVC学习笔记——完整的用户登录

    1.搭建环境的第一步是导包,把下面这些包都导入工程中 /media/common/工作/Ubuntu软件/SpringMVC_jar包整理/aop/media/common/工作/Ubuntu软件/S ...

  4. Servlet学习(三)——实例:用户登录并记录登陆次数

    1.前提:在Mysql数据库下建立数据库web13,在web13下创建一张表user,插入几条数据如下: 2.创建HTML文件,命名为login,作为登录界面(以post方式提交) <!DOCT ...

  5. Tornado 判断用户登录状态和操作权限(装饰器)

    判断是否登录: def authenticated(method): '''''' @functools.wraps(method) def wrapper(self, *args, **kwargs ...

  6. ant design pro v2 关于用户登录有多个权限的解决方法

    ant design pro V2菜单栏显示流程, 用户输入用户名,密码,登录调用登录接口,校验后返回该用户的权限字段currentAuthority,然后通过调用setAuthority(curre ...

  7. .Net Core3.0 WebApi 项目框架搭建 四:JWT权限验证

    .Net Core3.0 WebApi 项目框架搭建:目录 什么是JWT 根据维基百科定义,JWT(读作 [/dʒɒt/]),即JSON Web Tokens,是一种基于JSON的.用于在网络上声明某 ...

  8. SpringMVC学习系列(9) 之 实现注解式权限验证

    对大部分系统来说都需要权限管理来决定不同用户可以看到哪些内容,那么如何在Spring MVC中实现权限验证呢?当然我们可以继续使用servlet中的过滤器Filter来实现.但借助于Spring MV ...

  9. WebApi -用户登录后SessionId未更新

    描工具检测出.net的程序有会话标识未更新这个漏洞 用户尚未登录时就有session cookie产生.可以尝试在打开页面的时候,让这个cookie过期.等到用户再登陆的时候就会生成一个新的sessi ...

随机推荐

  1. ubuntu下出现的问题-控制台更新源失败

    Ubuntu下控制台输入sudo apt-get update之后出现的问题:E: Could not get lock /var/lib/apt/lists/lock - open (11: Res ...

  2. Java的四种引用方式

    一.引用基本概念 从JDK1.2版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期.这四种级别由高到低依次为:强引用.软引用.弱引用.虚引用. 1.强引用(StrongRef ...

  3. 模拟--poj1835宇航员的故事

    这道题委实无语了,刚开始以为是很一般的方位模拟题,懒得看样例直接写的代码,然后敲了好几个switch结果样例居然没出来.. 仔细分析了样例之后才发现原来随着宇航员方位的改变他的左手方向以及头顶方向是跟 ...

  4. ajax的理解与工作流程

    一.什么是ajax ajax是一种异步通信技术.在ajax出现之前,客户端与服务端之间直接通信.引入ajax之后,客户端与服务端加了一个第三者--ajax.有了ajax之后,通过在后台与服务器进行少量 ...

  5. markdown预览-快速入门

    最近要写文档,领导指定用markdown. 这个两三年前用过两次的神器工具,都忘的差不多了. 为了熟练一点这个技能,决定好好的重新学一次. 于是乎:看快速入门文档 ...30分钟...看完文档发现要来 ...

  6. 有关JVM配置参数含义

    1.参数的含义-vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M-vmargs 说明后面是VM的参数,所以后面的其实都是JV ...

  7. 安卓初級教程(3):ContentProvider的運用原理

    package com.example.android.provider; import java.util.ArrayList; import java.util.HashMap; import j ...

  8. ex1-第一个程序 ”helloworld”

    代码: print("Hello world.")print("Hello again.")print("I like typing this.&qu ...

  9. 在 Windows 上安装Rabbit MQ 指南

    rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.他遵循Mozilla Public License开源协议.采用 Erlang 实现的工业级的消息队列(MQ)服务器. Ra ...

  10. ABP理论学习之通知系统

    返回总目录 本篇目录 介绍 订阅通知 发布通知 用户通知管理者 实时通知 通知存储 通知定义 介绍 通知(Notification)用于告知用户系统中的特定事件.ABP提供了基于实时通知基础设施的发布 ...