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 实现验证之一:统一拒绝非登录访问。的更多相关文章

  1. 将最小的OWIN身份验证添加到现有的ASP.NET MVC应用程序

    https://weblog.west-wind.com/posts/2015/Apr/29/Adding-minimal-OWIN-Identity-Authentication-to-an-Exi ...

  2. Asp.Net WebApi 使用OWIN架构后,出现 “没有 OWIN 身份验证管理器与此请求相关联(No OWIN authentication manager is associated with the request)” 异常的解决办法

    在Asp.Net WebApi 项目中使用OWIN模块之后,如果没有在OWIN的Startup类中配置认证方式,调用WebApi的相关Controller和Action就会出现如下异常: 出现错误. ...

  3. MVC的验证(模型注解和非侵入式脚本的结合使用) .Net中初探Redis .net通过代码发送邮件 Log4net (Log for .net) 使用GDI技术创建ASP.NET验证码 Razor模板引擎 (RazorEngine) .Net程序员应该掌握的正则表达式

    MVC的验证(模型注解和非侵入式脚本的结合使用)   @HtmlHrlper方式创建的标签,会自动生成一些属性,其中一些属性就是关于验证 如图示例: 模型注解 通过模型注解后,MVC的验证,包括前台客 ...

  4. aspnet core 全局模型验证,统一api响应

    上手就来 新建一个模型验证过滤器,其中ApiResp是自定义的统一响应类. public class VldFilter:IActionFilter { /// <summary> /// ...

  5. 两系统用asp.net forms 身份验证方式实现跨域登录信息共享

    1.两个系统的 web.config 都配置为 forms 验证方式( system.web —> authentication 节点) 2.在两个系统的Web.config里配置相同的 sys ...

  6. ASP.NET MVC 4.0中选择Windows 验证默认出错拒绝访问的原因和解决方案

    在VS 2012或者2013 中,根据模板创建一个ASP.NET MVC 4.0的应用程序,选择下面的模板 然后选择Intranet Application 不对源代码做任何修改,直接按下F5调试,会 ...

  7. 【IP限制】验证是否限制了境外IP访问权限

    为啥要限制境外IP访问咱们的网站或者服务呢?怕泄漏了"机密"(好像都是我们在山寨别人,哪儿TM有机密,那叫"鸡贼") 好像国外的网站也没有限制咱大陆客去访问,反 ...

  8. Struts(二十四):短路验证&重写实现转换验证失败时短路&非字段验证

    短路验证: 若对一个字段使用多个验证器,默认情况下会执行所有的验证.若希望前面的验证器没有通过,后面的验证器就不再执行,可以使用短路验证. 1.如下拦截器,如果输入字符串,提交表单后,默认是会出现三个 ...

  9. 实现Redhat Linux 6和Windows通过Windows Server AD统一认证并共享访问Oracle ZS存储系统

    Windows Server 2012 AD设置 1.  建立新的组织单位OU 为用户提前建立好OU,是为了AD用户管理简单清晰. 2.  建立新的用户和用户组 建立新的用户的时候,要同时将用户归属到 ...

随机推荐

  1. 后台返回xml格式转json

    之前后台做了一个xml格式的数据返回给前端,这个可愁坏了我,不过现在还是解决了,虽然方法有点笨,但没有找到其他的方法,先将就着用吧. 后台返回的是这样的: 那么我们就要这样处理:commonMetho ...

  2. 创建Android Apps的30个经验教训

    这个世界上有两种人-从经验教训中学习的人以及听从别人建议的人.这里是我一路走来学到的一些东西,分享给大家: 在添加任何第三方party之前,请三思:这真的是一个成熟的项目吗? 如果一个东西用户看不到, ...

  3. python网络编程:socket、服务端、客户端

    本文内容: socket介绍 TCP: 服务端 客户端 UDP: 服务端 客户端 首发时间:2018-02-08 01:14 修改: 2018-03-20 :重置了布局,增加了UDP 什么是socke ...

  4. 【CSS基础】实现 div 里的内容垂直水平居中

    方案一: 所有内容垂直水平居中 兼容性:IE8+. 条件:内容宽度和高度可以未知,可以是多行文字.图片.div. 描述:使用table-cell + vertical-align , html代码见文 ...

  5. python第四十八天--高级FTP

    高级FTP服务器1. 用户加密认证2. 多用户同时登陆3. 每个用户有自己的家目录且只能访问自己的家目录4. 对用户进行磁盘配额.不同用户配额可不同5. 用户可以登陆server后,可切换目录6. 查 ...

  6. 什么是ORM?为啥要是用ORM?

    了解orm,先了解以下概念: 什么是“持久化” 持久(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘).持久化的主要应用是将内存中的数据存储在关系型的数据库中 ...

  7. mybatis 字段类型Data相

    在项目中查询时间段的sql语句(时间类型为datetime或date)(数据库中的时间类型): <if test="beginTime!=null and beginTime!=''& ...

  8. ccf--20140303--命令行选项

    本题是常规思路,这里要注意:1)带参命令没有参数和参数错误时终止2)命令不存在时终止3)命令都是错误的,不以—开头. 题目和代码如下: 问题描述 试题编号: 201403-3 试题名称: 命令行选项 ...

  9. 使用hint优化Oracle的运行计划 以及 SQL Tune Advisor的使用

    背景: 某表忽然出现查询很缓慢的情况.cost 100+ 秒以上:严重影响生产. 原SQL: explain plan for select * from ( select ID id,RET_NO ...

  10. 使用idea搭建SSM框架

    搭建个SSM框架居然花费了我好长时间!特此记录! 需要准备的环境: idea 2017.1 jdk1.8 Maven 3.3.9  请提前将idea与Maven.jdk配置好,本次项目用的都是比较新的 ...