近些天,看了一些博客园大牛关于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. javascript 创建对象的7种模式

    使用字面量方式创建一个 student 对象: var student = function (){ name : "redjoy", age : 21, sex: women, ...

  2. ThinkPHP5 与 ThinkPHP3.* 之间的使用差异

    因为研究TP5时间不是很长,暂时先列以下几处差异: 1.过去的单字母函数已完全被替换掉,如下: S=>cache,C=>config,M/D=>model,U=>url,I=& ...

  3. 配置iis时,浏览项目提示 无法识别的属性“targetFramework”。请注意属性名称区分大小写。

    无法识别的属性“targetFramework”.请注意属性名称区分大小写. 行 12:     </appSettings>行 13:   <system.web>行 14: ...

  4. laravel 生成验证码的方法

    在Laravel中有很多图片验证码的库可以使用,本篇介绍其中之一:gregwar/captcha,这个库比较简单,在Laravel中比较常用.下面我们就来介绍下使用细节: 首先, composer.j ...

  5. C ReadProcessMemory

    ReadProcessMemory函数用于读取其他进程的数据. BOOL STDCALL ReadProcessMemory ( HANDLE hProcess, LPCVOID lpBaseAddr ...

  6. Concurrency并发性

    今天看了有关性能的文章,性能也是客户所看重的. 文章推荐看了软件编程并发性. 就按书上敲了网址看:http://www.gotw.ca/publications/concurrency-ddj.htm ...

  7. Python黑帽编程2.3 字符串、列表、元组、字典和集合

    Python黑帽编程2.3  字符串.列表.元组.字典和集合 本节要介绍的是Python里面常用的几种数据结构.通常情况下,声明一个变量只保存一个值是远远不够的,我们需要将一组或多组数据进行存储.查询 ...

  8. Java批处理ExecutorService/CompletionService

    服务端接收一个请求,常常需要同时进行几个计算或者向其他服务发送请求,最后拼装结果返回上游.本文就来看下JDK提供几个并行处理方案,牵涉到ExcecutorService/CompletionServi ...

  9. java stopwatch 功能

    C#中有一个stopwatch的功能,主要是用来监测程序执行时间的.java之前一直都在用如下方式完成: public static void main(String[] args) { long s ...

  10. Intellij IDEA 13.1.3 字体,颜色,风格设置

    作者QQ:1095737364 打开file-->settings,然后根据提示完成设置,当然,可以根据自己的爱好设置自己的风格,那个工程区的背景我还没有找到在什么地方,如果你找到了麻烦告诉我一 ...