anglarjs1.6.3+owin 实现验证之一:统一拒绝非登录访问。

1、anglarjs端在app.js(即anglar的入口js),注册.factory("messageService",使得每次来自html客户端的请求都能带有一个值,如AKey:
var chars = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];function generateMixed(n) { var res = ""; for(var i = 0; i < n ; i ++) { var id = Math.ceil(Math.random()*35); res += chars[id]; } return res;}var ClientID=generateMixed(6);
var Akey='ccc';
expressApp.factory('authInterceptor', function($rootScope){
return {
request: function(config){
config.headers = config.headers || {};
config.headers.authorization = Akey;
return config;
},
responseError: function(response){
)
{
debugger
location.href="./E403.html"
}
}
};
})
expressApp.config(function ($locationProvider, $routeProvider,$httpProvider) {
$httpProvider.interceptors.push('authInterceptor');
}
2、html客户端做一个403页面,页面带一个连接,连接跳转到登录页
<li>
使用具有访问权限的账户重新登录系统,点击:
<a href="./index.html#/login">此处</a>。
</li>
3、客户端包含一个登录页login.html,对应的关键js如下:
$http({
method: 'post', url: baseUrl+'account/login',
data: {
LoginName: $scope.LoginName,
Password:$scope.Password,
ClientID:ClientID
}
}).then(function (response) {
Akey=response.data.LogonUser.SessionKey;
},
function (response) {
}
);
这里面最重要的一句话,就是Akey=response.data.LogonUser.SessionKey; 因为Aky是在app.js里面定义的全局变量,所以登录之前是一个错误值,在服务端限定以后,不能访问任何常规的action,但是只能访问服务端的account/login这个action。
4、下来看看服务端的login这个action
[Route("express/account/login")]
public HttpResponseMessage Login(Users user)
{
if (string.IsNullOrEmpty(user.LoginName))
return Request.CreateResponse(HttpStatusCode.Forbidden);
if (string.IsNullOrEmpty(user.Password))
return Request.CreateResponse(HttpStatusCode.Forbidden);
var nowUser = auS.GetUserByUserId(user.LoginName);
if (nowUser == null)
return Request.CreateResponse(HttpStatusCode.Forbidden);
#region 验证密码
if (!string.Equals(nowUser.Password, user.Password))
{
return Request.CreateResponse(HttpStatusCode.Forbidden);
}
#endregion
if (nowUser.IsDelete)
return Request.CreateResponse(HttpStatusCode.Forbidden);
var existsDevice = auS.GetClientUser(nowUser.LoginName);
if (existsDevice == null)
{
string passkey = auS.ComputeHash(nowUser.LoginName + nowUser.ClientID + DateTime.UtcNow + Guid.NewGuid());
existsDevice = new Users()
{
LoginName = nowUser.LoginName,
SessionKey = passkey,
ClientID = user.ClientID
};
auS.AddClientUser(existsDevice);
}
else
{
auS.UpdateUserDevice(existsDevice);
}
existsDevice.Password = "";
return Request.CreateResponse(HttpStatusCode.OK, new SessionObject() { SessionKey = existsDevice.SessionKey, LogonUser = existsDevice });
}
这里面最关键的一个就是这两句话,当客户端发来一个clientID以后,使用一定的规则合成一个会话ID,存到内存中一个静态列表里面,以实现只要登录一次且不超时,就缓存这个人的登录信息,相当于session一样的效果。
string passkey = auS.ComputeHash(nowUser.LoginName + nowUser.ClientID + DateTime.UtcNow + Guid.NewGuid()); ClientID = user.ClientID
那么在来看看app.js里面的这个ClientID:
','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
function generateMixed(n) {
var res = "";
; i < n ; i ++) {
);
res += chars[id];
}
return res;
}
);
5、来看看AuthenticationService.cs的一些关键代码:这里也可以用字典,甚至可以把列表迁移到redis上面去都可以。
public string ComputeHash(string input)
{
byte[] data = Md5.ComputeHash(Encoding.Unicode.GetBytes(input));
var sBuilder = new StringBuilder();
foreach (byte t in data)
sBuilder.Append(t.ToString("X"));
return sBuilder.ToString();
}
/// <summary>
/// 使用唯一标识获得登录用户
/// </summary>
/// <param name="Akey"></param>
/// <returns></returns>
public Users GetClientUserByAkey(string Akey)
{
//headers.Authorization.Scheme
var ul = ClientUser.Where(_ =>
{
return _.SessionKey == Akey;
});
)
{
var u = ul.FirstOrDefault();
if (u.ExpiredTime < DateTime.Now)
{
return u;
}
else
{
ClientUser.Remove(u);
}
}
return null;
}
public Users GetUserByUserId(string loginName)
{
//Accessor是我写的一个ORM的访问器
var ul = Accessor.GetList<Users>(new { LoginName = loginName });
return ul.FirstOrDefault();
}
首先BaseController继承自ApiController,而且用于登录的那个Controller也就是AccountController必须继承自 ApiController
AccountController : ApiController
BaseController: ApiController
再来看看BaseController的关键代码,这样我们写业务Controller(非登录AccountController)的时候,比如ProductController,让ProductController:BaseController即可
public Express.Entity.Users currentUser = null;
public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
{
if (controllerContext.Request.Headers.Authorization != null
&& !string.IsNullOrWhiteSpace(controllerContext.Request.Headers.Authorization.Scheme))
{
currentUser = new AuthenticationService().GetClientUserByAkey(controllerContext.Request.Headers.Authorization.Scheme);
if (currentUser == null)
{
var response = new HttpResponseMessage(HttpStatusCode.Forbidden);
var tsc = new TaskCompletionSource<HttpResponseMessage>();
tsc.SetResult(response);
return tsc.Task;
}
}
else
{
var response = new HttpResponseMessage(HttpStatusCode.Forbidden);
var tsc = new TaskCompletionSource<HttpResponseMessage>();
tsc.SetResult(response);
return tsc.Task;
}
return base.ExecuteAsync(controllerContext, cancellationToken);
}
好了,下一篇讲述,如果实现粒度到action级别的权限控制。
anglarjs1.6.3+owin 实现验证之一:统一拒绝非登录访问。的更多相关文章
- 将最小的OWIN身份验证添加到现有的ASP.NET MVC应用程序
https://weblog.west-wind.com/posts/2015/Apr/29/Adding-minimal-OWIN-Identity-Authentication-to-an-Exi ...
- Asp.Net WebApi 使用OWIN架构后,出现 “没有 OWIN 身份验证管理器与此请求相关联(No OWIN authentication manager is associated with the request)” 异常的解决办法
在Asp.Net WebApi 项目中使用OWIN模块之后,如果没有在OWIN的Startup类中配置认证方式,调用WebApi的相关Controller和Action就会出现如下异常: 出现错误. ...
- MVC的验证(模型注解和非侵入式脚本的结合使用) .Net中初探Redis .net通过代码发送邮件 Log4net (Log for .net) 使用GDI技术创建ASP.NET验证码 Razor模板引擎 (RazorEngine) .Net程序员应该掌握的正则表达式
MVC的验证(模型注解和非侵入式脚本的结合使用) @HtmlHrlper方式创建的标签,会自动生成一些属性,其中一些属性就是关于验证 如图示例: 模型注解 通过模型注解后,MVC的验证,包括前台客 ...
- aspnet core 全局模型验证,统一api响应
上手就来 新建一个模型验证过滤器,其中ApiResp是自定义的统一响应类. public class VldFilter:IActionFilter { /// <summary> /// ...
- 两系统用asp.net forms 身份验证方式实现跨域登录信息共享
1.两个系统的 web.config 都配置为 forms 验证方式( system.web —> authentication 节点) 2.在两个系统的Web.config里配置相同的 sys ...
- ASP.NET MVC 4.0中选择Windows 验证默认出错拒绝访问的原因和解决方案
在VS 2012或者2013 中,根据模板创建一个ASP.NET MVC 4.0的应用程序,选择下面的模板 然后选择Intranet Application 不对源代码做任何修改,直接按下F5调试,会 ...
- 【IP限制】验证是否限制了境外IP访问权限
为啥要限制境外IP访问咱们的网站或者服务呢?怕泄漏了"机密"(好像都是我们在山寨别人,哪儿TM有机密,那叫"鸡贼") 好像国外的网站也没有限制咱大陆客去访问,反 ...
- Struts(二十四):短路验证&重写实现转换验证失败时短路&非字段验证
短路验证: 若对一个字段使用多个验证器,默认情况下会执行所有的验证.若希望前面的验证器没有通过,后面的验证器就不再执行,可以使用短路验证. 1.如下拦截器,如果输入字符串,提交表单后,默认是会出现三个 ...
- 实现Redhat Linux 6和Windows通过Windows Server AD统一认证并共享访问Oracle ZS存储系统
Windows Server 2012 AD设置 1. 建立新的组织单位OU 为用户提前建立好OU,是为了AD用户管理简单清晰. 2. 建立新的用户和用户组 建立新的用户的时候,要同时将用户归属到 ...
随机推荐
- 惊闻企业Web应用生成平台 活字格 V4.0 免费了,不单可视化设计器免费,服务器也免费!
官网消息: 针对活字格开发者,新版本完全免费!您可下载活字格 Web 应用生成平台 V4.0 Updated 1,方便的创建各类 Web 应用系统,任意部署,永不过期. 我之前学习过活字格,也曾经向用 ...
- Kotlin入门(10)七十二变的输入参数
上一篇文章介绍了Kotlin对函数的基本用法,包括函数的定义.输入参数的声明.输出参数的声明等等,这些足够对付简单的场合了.当然了,倘若一门新语言仅仅满足于这些雕虫小技,那也实在没什么前途.既然Kot ...
- Android--获取高清的app图标
只有一个方法. public synchronized static Drawable getIconFromPackageName(String packageName, Context conte ...
- centos-7 虚拟机安装图形界面
centos-7 虚拟机安装图形界面 想到安装一个docker环境,于是拿出了以前装的虚拟机centos7,记得装完后,没进行任何配置(默认安装的是命令行界面). 配置网络 现有的虚拟机是没有办法联网 ...
- 服务器较稳妥的磁盘阵列方案:RAID5+热备盘
最近公司这边要整个数据中心,但是我们这边磁盘阵列的方案选择方面需要做好万全的测试 内部测试的服务器当初损坏的磁盘1个做的raid5直接换个新磁盘做替换rebuild就行了 但是现在想的方法是5+1的方 ...
- awk实战演示
awk:报告生成器,格式化文本输出. 我们一般使用的awk命令其实就是gawk,在centos7系统下,awk是gawk的链接文件. 基本用法:gawk [options] 'program' FI ...
- Linux 小知识翻译 - 「分区」
安装Linux的时候,需要对硬盘进行分区.那么「分区」到底是什么呢? 「分区」在日语中有区分,分割的意思.计算机术语中有时会说「对一个磁盘进行分区」,整个意思就是指定如何分割磁盘的意思. 「对磁盘进行 ...
- python基础 - 字符串作
split(sep=None, maxsplip=-1) 从左到右 sep 指定分隔字符串,缺省情况下空白字符串,指定的字符串会被切掉 maxsplit 指定分隔次数,-1 表示遍历 rsplit(s ...
- 【数据库】事务,ACID,CAP和一致性
什么是事务 事务是指由一系列数据库操作组成的一个完整的逻辑过程,这个过程中的所有操作要么都成功,要么都不成功.比如:常见的例子就是银行转账的例子,一次转账操作会包含多个数据库操作,而这些数据库操作需要 ...
- map && multimap
map map 的意思是映射.用法一般是 map<char, int>mp 按照我的理解,map 类似于一个高级的数组.前面的数据类型 char 相当于下脚标,而数组元素的值就对应 ...