管理【转】权限管理上 一、ASP.NET Forms身份证明

【转】权限管理上 一、ASP.NET
Forms身份认证

粗粗八月份的时光做了一个关于两只SAP系统内部资产摊传输的门类,使用及了RFC(Remote
Function
Call)技术。因为前面有医疗-CRM相关接口开发的阅历,以为自己对RFC很熟稔了,做起来会死顺利,不思要么碰到了头问题。打算整治一下有关其的情,进一步读书。

证实:本文示例使用的VS2017以及MVC5。
网无论大小、牛逼或屌丝,一般都离不起头注册、登录。那么接下去我们不怕来分析下用户身份认证。

正文内容的基本点源于是SAP的英文文档。会于青睐基本概念上之事物,偶尔涉及实际的代码、配置。后续可能会见根据自己之实际上用状况更新更详实的介绍。

简单实现登录、注销

以前在学习.net的时节不懂得什么Forms身份验证,直接用session实现登录,效果啊异常好嘛。而且用户信息存在服务端,安全。
前端代码:

@if (string.IsNullOrWhiteSpace(ViewBag.UserName))
{
    <form action="/home/login1">
        <input type="text" name="userName" />
        <input type="submit" value="登录" />
    </form>
}
else
{
    <form action="/home/logout1">
        <div>当前用户已登录,登录名:@ViewBag.UserName</div>
        <input type="submit" value="退出" />
    </form>
}

后台代码:

public ActionResult Index()
{
    ViewBag.UserName = Session["userName"]?.ToString();           
    return View();
}       

public void Login1(string userName)
{
    if (!string.IsNullOrWhiteSpace(userName))  //为了方便演示,就不做真的验证了     
        Session["userName"] = userName;
    else
        Session["userName"] = null;
    Response.Redirect(Request.UrlReferrer.LocalPath);//重定向到原来页面
}

public void Logout1()
{
    Session["userName"] = null;
    Response.Redirect(Request.UrlReferrer.LocalPath);//重定向到原来页面
}

凡匪是,简单明了。想只要自己扩大或是定制什么效益还充分好用。不过我们要维护session。比如系统更颁发,或者iis被电动重新开。就会见起session丢失的景象。也就是用户会莫名其妙提升要重新登录。体验好不好。(这里先不讨论session服务和数据库的状况)。既然微软有一致效成熟之权柄管理我们为什么不要吧?

 

Forms认证登录、注销

先是以web.config里开Forms身份证明:

<system.web>
  <authentication mode="Forms"></authentication>

后台代码:

public void Login2(string userName)
{
    if (!string.IsNullOrWhiteSpace(userName))  //为了方便演示,就不做真的验证了
        FormsAuthentication.SetAuthCookie(userName, true); //登录
    Response.Redirect(Request.UrlReferrer.LocalPath);//重定向到原来页面
}

public void Logout2()
{
    FormsAuthentication.SignOut();//登出
    Response.Redirect(Request.UrlReferrer.LocalPath);//重定向到原来页面
}

前台代码:

@if (!Request.IsAuthenticated)
{
    <form action="/home/login2">
        <input type="text" name="userName" />
        <input type="submit" value="登录" />
    </form>
}
else
{
    <form action="/home/logout2">
        <div>当前用户已登录,登录名:@Context.User.Identity.Name</div>
        <input type="submit" value="退出" />
    </form>
}

如此几句子代码就贯彻了俺们的登录和收回。和我们温馨之所以session管理登录不同。Forms身份验证是直拿消息存cookie到浏览器的。通过SetAuthCookie这个方法名也得以拘留出来。不过Cookie信息经过了加密。
这边发出必要说明session和cookie的干。当我们采用session来保障用户状态的时刻,其实呢祭了cookie。
管理 1
不过Forms身份验证仅仅只是把信存了cookie,而从不在服务端维护一个对应的session。
非信教而可测试。可以据此鲜栽艺术还登录,然后去掉session就好测量出来了。(怎么清session?重开iis,或者涂改下后台代码在重复编译访问)
【说明】用户征为什么要存cookie?因为HTTP是一个凭状态的商事。对于服务器来说,每次要都是相同的。所以,只能通过每次要带的cookie来分辨用户了。(暂时不考虑任何办法)

正文链接:http://www.cnblogs.com/hhelibeb/p/8066753.html

自定义之身份证明标识

方使用的登录很简单,但事实上状况屡屡十分复杂。明显正常工作需要存的用户信息会要重复多。那么我们是否可以扩大身份标识也?答案是必定之。
后台代码:

public void Login3(string userName)
{
    if (!string.IsNullOrWhiteSpace(userName))  //为了方便演示,就不做真的验证了     
    {
        UserInfo user = new UserInfo()
        {
            Name = userName,
            LoginTime = DateTime.Now
        };
        //1、序列化要保存的用户信息
        var data = JsonConvert.SerializeObject(user);

        //2、创建一个FormsAuthenticationTicket,它包含登录名以及额外的用户数据。
        FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(2, userName, DateTime.Now, DateTime.Now.AddDays(1), true, data);

        //3、加密保存
        string cookieValue = FormsAuthentication.Encrypt(ticket);

        // 4. 根据加密结果创建登录Cookie
        HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, cookieValue);
        cookie.HttpOnly = true;
        cookie.Secure = FormsAuthentication.RequireSSL;
        cookie.Domain = FormsAuthentication.CookieDomain;
        cookie.Path = FormsAuthentication.FormsCookiePath;

        // 5. 写登录Cookie
        Response.Cookies.Remove(cookie.Name);
        Response.Cookies.Add(cookie);
    }
    Response.Redirect(Request.UrlReferrer.LocalPath);//重定向到原来页面
}

然后在Global.asax的Application_AuthenticateRequest方法:

protected void Application_AuthenticateRequest()
{
    GetUserInfo();
}

//通过coolie解密 读取用户信息到 HttpContext.Current.User
public void GetUserInfo()
{
    // 1. 读登录Cookie
    HttpCookie cookie = Request.Cookies[FormsAuthentication.FormsCookieName];

    try
    {
        UserInfo userData = null;
        // 2. 解密Cookie值,获取FormsAuthenticationTicket对象
        FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);

        if (ticket != null && string.IsNullOrEmpty(ticket.UserData) == false)
            // 3. 还原用户数据
            userData = JsonConvert.DeserializeObject<UserInfo>(ticket.UserData);

        if (ticket != null && userData != null)
            // 4. 构造我们的MyFormsPrincipal实例,重新给context.User赋值。
            HttpContext.Current.User = new MyFormsPrincipal<UserInfo>(ticket, userData);
    }
    catch { /* 有异常也不要抛出,防止攻击者试探。 */ }
}

前者代码:

@{
    MyFormsPrincipal<UserInfo> user = Context.User as MyFormsPrincipal<UserInfo>;
    if (user == null)
    {
        <form action="/home/login3">
            <input type="text" name="userName" />
            <input type="submit" value="登录" />
        </form>
    }
    else
    {

        <form action="/home/logout2">
            <div>当前用户已登录,登录名:@Context.User.Identity.Name</div>
            <div>当前用户已登录,登录时间:@user.UserData.LoginTime</div>
            <input type="submit" value="退出" />
        </form>
    }
}

事实上任何经过和FormsAuthentication.SetAuthCookie(userName, true); //登录凡是一模一样的。只是我们通过扩充,存了咱们怀念只要存储的数量。
过程为比较简单:

  • 布局要存储的多少
  • 序列化
  • 管序列化信息放入FormsAuthenticationTicket对象
  • 由此FormsAuthentication.Encrypt加密对象
  • 出殡cookie到浏览器

此地小复杂点的地方就是解密然后给User赋值HttpContext.Current.User = new MyFormsPrincipal<UserInfo>(ticket, userData);
MyFormsPrincipal需要贯彻接口MyFormsPrincipal

public class MyFormsPrincipal<TUserData> : IPrincipal where TUserData : class, new()
{
    private IIdentity _identity;
    private TUserData _userData;

    public MyFormsPrincipal(FormsAuthenticationTicket ticket, TUserData userData)
    {
        if (ticket == null)
            throw new ArgumentNullException("ticket");
        if (userData == null)
            throw new ArgumentNullException("userData");

        _identity = new FormsIdentity(ticket);
        _userData = userData;
    }

    public TUserData UserData
    {
        get { return _userData; }
    }

    public IIdentity Identity
    {
        get { return _identity; }
    }

    public bool IsInRole(string role)//这里暂时不实现
    {
        return false;
    }
}

相反也未曾呀特别,就是实例化的时段传出票据及自定义数据就是好了。

总述

对此SAP与SAP系统以及SAP与非SAP系统中的连而言,远程函数调用(Remote
Function
Call,以下简称RFC)是均等栽标准的通信方式,它可兑现对长距离系统面临函数的调用。

具备RFC类型都通过CPI-C或TCP/IP协议进行传输。
它们做了相同种植Gateway通信。

本文是本着持有RFC变体的叙述,它们持有不同的表征与副的行使状况。

授权

发了登录一般都去不开授权。微软的物好就算哼于,一般都是一体成套的。

[Authorize]
public ActionResult LoginOk()
{
    return View();
}

一直叫Action添加一个Authorize特性就哼了,这口就会自动检查是不是登录。如果无登录活动跳反到登录页面。登录页面的安装或于web.config里面

<system.web>
  <authentication mode="Forms" >
    <forms loginUrl="/home/index"></forms>

这种概括的授权验证明显是不够的。很多时刻某些页面只有某些人才能够看。比如VIP。那么我们还要使壮大了。

//继承 AuthorizeAttribute
public class MyAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.User.Identity.Name != "农码一生")
        {
            filterContext.HttpContext.Response.Write("您不是vip用户,不能访问机密数据");
            filterContext.HttpContext.Response.End();
            return;
        }
        base.OnAuthorization(filterContext);
    }
}

[MyAuthorize]
public ActionResult LoginVIP()
{
    return View();
}

毋庸置疑,就是这样简单。说了如此多,来张效果图吧:
管理 2

 

引进阅读:

  • http://www.cnblogs.com/fish-li/archive/2012/04/15/2450571.html
    Demo:
  • https://github.com/zhaopeiym/BlogDemoCode/tree/master/权限管理/1-Forms身份验证

 

同步RFC:sRFC

与步RFC(Synchronous
RFC,sRFC)是最为中心的RFC形式。在sRFC调用中,调用者会等待远程被调用者的处理过程。

它们的语法形式是:

CALL FUNCTION func DESTINATION dest. 

典型的运状况包括:

  • 销售:为不同体系创造市订单(central sales)。
  • 销售:对于有查询,在供应商系统里实施一个对此指定物料的可用性检查。
  • 物品管理:在外一个系里对有物料订单执行来源判断。
  • CRM/SRM:对SAP后端系统倡导某个物料的可用性检查。
  • CRM/SRM:在SRM组件中创造市订单时,在先生集中核算中呢公的老本中心开展预算检查。
  • 会计师:向先生集中核算体系要一个成本中心清单。
  • BW:调用BW组件(商业信息仓库)来呼吁一个特意之evaluation。

异步RFC:aRFC

异步RFC(Asynchronous
RFC,aRFC)类似与tRFC,用户以后续调用会话之前,不需要拭目以待她的好。不过,aRFC和tRFC之间也有几乎触及不同之地方:

  • 当调用者开始一个aRFC的时光,被调用的服务器必须得接到请求。aRFC的参数不会见记录在数据库被,而是一直发送给对方服务器。
  • aRFC允许用户和远程系统开展交互式对话。
  • 调用程序可以由aRFC接收结果。

君得在当您用建立与一个远端系统的连日、但是期望当调用RFC后未希望等结果而是期待后续处理常采取aRFC。aRFC也堪发送给同样的网。在这种情况下,系统打开一个新的对话(窗口)。你得于调用对话与给调用会话间切换。使用下的言辞开启一个aRFC:

CALL FUNCTION Remotefunction STARTING NEW TASK Taskname

DESTINATION ...

EXPORTING...

TABLES ...

EXCEPTIONS...

 RECEIVE RESULTS FROM FUNCTION Remotefunction 用于一个子先后外经受aRFC的调用结果。可以应用以下收取参数:

  • IMPORTING

  • TABLES

  • EXCEPTIONS

附加项KEEPING
TASK
截留连接在收到处理结果后关门。相关的长途上下文(滚动区域)保持好用的状态,直至调用者终止连接。

还多关于aRFC的音可以从以下地方获得:

  • aRFC的调用属性

  • 自打aRFC接收结果

  • 保持远程上下文

  • aRFC的并行处理

关于aRFC变体的叙述:

  • CALL FUNCTION – STARTING NEW
    TASK

  • RECEIVE

  • WAIT
    UNTIL

  • RFC示例

事务RFC:tRFC

以应用事务RFC( transactional
RFC,tRFC)的时光,被调用的函数模块于受调用系统受恰恰运行一蹩脚(Exactly Once)。

远端系统非需要在RFC客户端程序运行tRFC的下可用。tRFC组件将给调用的RFC函数和有关数据存储于SAP系统的数据库里,包含一个唯一的事情标识符(transaction
identifier,TID)。

倘若调用发送了,接收系统却是宕机状态,调用会保留在当地队列中一段时间。调用对话程序可以于匪待远程调用成功/失败的事态下连续运行。如果接受系统在一段时间后还未可用,调用将被计划呢后台作业运行。

tRFC使用后缀IN BACKGROUND TASK.

即跟合调用一样,参数
DESTINATION在长途系统定义了先后上下文。结果是,如果你对一个destination重复地调用一个函数(或者一次性调用多单函数),则足以当平之内外文中访问被调用函数的大局数据。。

系会于表ARFCSSTATE和表ARFCSDATA中著录远程连接要和它的整整参数值。你得用事务SM58来查。当调用程序到达COMMIT
WORK
言辞时,远程调用会让转接到为对方系统。

在两个COMMIT
WORK
里,所有的具备和一个destination的tRFC属于同一个逻辑单元(LUW)。

tRFC处理流图示:

管理 3

乃可于好几情况下下下tRFC,比如,对于用以业务的不比阶段更新相关数据库表的繁杂的处理过程。

tRFC会确保所有的计划更新在次到达COMMIT WORK语句时叫执行。

(注意:tRFC的定义着莫能够生出任何EXPORT参数,因为调用程序中而起IMPORT参数,就见面招语法错误。此外,你也未可以针对实行回调的次第进行异步调用)

系可用性:

要远程系统非可用,SAP系统会将报表RSARFCSE计划吧后台作业,并拿相关的工作ID作为变式,再开展处理。这个表程序会重复地吃调用,直到它成功地连对方系统了。

当给计划也后台作业时,RSARFCSE自动地因一个岁月距离运行(默认是各级15分钟运行一不好,最多尝试30不行)。你可以由此加强程序SABP0000和SABP0003来自定义该时间距离。

经过SM59配备destination,选择一个destination并且选择
编辑->TRFC选项,在此处定义连接尝试次数上限和重复连接尝试的日距离。

管理 4

而以尝指定的次数后依然不足抵达相应的网,系统会停调用RSARFCSE,并形容副状态CPICERR至表ARFCSDATA中。在其他一个指定的时空后(默认是8天),在表ARFCSSTATE内之条条框框也会见给删。当然也足以定制者时刻,或者手动在SM59起先相应的政工条目。

tRFC的缺点:

  • tRFC独立地拍卖所有LUW。根据激活的tRFC数量,程序来或会见明显地降低调用系统以及受调用系统的习性。
  • 除此以外,在动用被定义之LUW的调用顺序是免克收获保障的。因此无法确保事务会按照使用期望之逐条运行。tRFC唯一能确保的只有:所有LUW都见面或早或晚地吃传。

可当此翻tRFC语句的叙述:

CALL FUNCTION IN BACKGROUND
TASK

队列RFC:qRFC

班RFC(queued Remote Function
Call,qRFC)是tRFC的一个扩展。它同意而以多只tRFC调用序列化为一个队。

qRFC调用会首先让函数模块TRFC_SET_QUEUE_NAME进行序列化处理,然后这些调用被一个tRFC进行实际的dispatch。

qRFC可以视作他望行(由调用系统序列化)处理,或者是内为行(由被调用系统序列化)。

* *

以下是三栽业务数据传的气象(为什么图片被的契是德文?):

管理 5

场景1:tRFC

欠现象适用于数据交互间独立发送的情事。系统1遇存在一个调用应用(client)使用tRFC连接系统2惨遭之让调用应用(r
server)。在该场景中,数据由tRFC传输,意味着发送到对象体系的函数模块调用会叫保单独运行一潮。你免得以定义函数模块运行的逐条及日。如果传输过程遭到起了不当,系统会计划一个后台作业,在15分钟后再发送函数模块调用。

场景2:带有外为行的qRFC

以该场景中,发送系统采取一个活跃队列来序列化被发送的多少。这意味着发送系统的活泼队列包含着是依靠关系之函数模块调用。当数码发送时,会维持确定的依次,并且调用会以正好同一不良都有序的点子(exactly once in order)发送给目标体系。

只顾:目标体系处理常莫需要改变qRFC的一一,但是,它要开启tRFC功能。

此情此景3:带有内往行的qRFC(以及活跃队列)

在这景下,不仅发送系统(client)有客望行,目标体系啊发内于行。如果qRFC存在有外为行,这吗象征它们在殡葬系统及肯定有外于行。内于行在一段时间里只能处理系统资源允许处理的函数模块调用数量。它可防服务器被一个客户端阻塞。只有在劳动体系独立在一个舅往行的景象是免可能是的,因为急需以客户端系统存在外于行,来安装顺序并截留单独的运阻塞客户端系统的全方位工作经过。

再多系信息可见:

  • Queued Remote Function Call
    (qRFC)

后台RFC:bgRFC

使用

bgRFC(Background Remote Function
Call)允许被调用程序稍晚一些接收数据,而不是联合接收。接收数据的时刻,需要保证数据只现出同等次还无序(
transactional) 、或者只现出同破还有序(queued)。

运用bgRFC进行异步调用,会生出如下优势:

  • 当跟一个SAP系统外(同一个体系ID,同一个client):解耦,同时提供了连行化能力。负载会分布在该体系的可用的应用服务器上。这个bgRFC场景被当做一个舅于程序。

  • 当点滴单远程SAP系统中:解耦,并且通过可以兑现利用或作业场景的大体细分。异步调用的结果是,调用者和于调用者的应用服务器的重点特性差异可以博得平衡。记录工作以调用系统中就。这个场景是一个活跃程序。

  • 点滴只次成为外-内程序:该办法可获取周优化增选之优势。不过,如果您选择了如此做,数据会被记录点滴次等,一不成是调用者(外向处理)、一差是为调用应用(
    内向程序的超常规类型)。这招数据库、应用服务器会时有发生额外的背。

bgRFC使用队列组织不同的调用。当一个调用同时深受放置于多独序列的下,系统会为这些队列创建依赖。这带来了一个同步点(synchronization
point),类似于锁。

要是一个调用处于依赖队列中,那么当且只有当她坐落依赖队列的极端上层时,它才会让拍卖。

对与一个destination,不得以将bgRFC和tRFC、qRFC结合起来用。不过,对于不同之destination,你得定义你想行使的简报类。

语法:

 CALL FUNCTION 'function_name'

IN BACKGROUND UNIT unit

          EXPORTING ... 

 

集成

由qRFC转换为bgRFC的应用程序,必须支持创造qRFC中之行列与bgRFC中之排中的即链接的搬迁方案。通过如此的方案,可以保证对的行顺序,即便是当起qRFC变为bgRFC的随时。

小心:从bgRFC改回qRFC是无可能的。

当SAP NetWeaver Release
7.11及更胜的本及,bgRFC也堪和basXML(二进制ABAP序列化XML)通信协议一起行使。

架构

俗的qRFC模型只有当数被RFC调度程序处理的早晚才探测各个独立单元内的依关系。对于每个destination,外向调度程序还见面敞开一个调度程序来拍卖此destination的多少。

暨之相对的是,bgRFC的依靠关系在数存储的时就控制了。通过这样做,RFC调度程序可以一次性找到有的需要吃拍卖的单元,并且经过最小之极力(minimum
effort)就可找到她中间的赖关系。在仓储数据的早晚用付的附加努力,则可以异常非常程度达由数据库设计中之高效率算法和优化补偿。

每个客户端定义一定数额之活泼计划,并且并行处理队列负载,虽然目标体系的负载会在一个比较短的时光间隔后叫确定,但是也因而会面更为精确。

单元与排的删除程序

跟人情的次不同,如果发另外单元或队列被去除,依赖还会维持。因为单元会于事先打上号,并且于即时之后只是给调度程序删除。

管理 6

若是图,在剔除了Unit4之后,Unit6只会当Unit3之后运行,因为Unit4只有当调度程序处理过Unit3之后才会受删去。如果您去掉queue2,那么会生下面的情景:

管理 7

Unit6见面以Unit2其后运行,所有选定的unit都见面为调度程序删除。

专注:删除队列或者单元总是有高风险的。在我们的例证里,它见面招Unit6遇到错误,或者造成目标体系的数据库不一致,因为它的前提Unit4因为吃删去而尚未运行。

Gateway:Gateway是另一个私房的性质瓶颈,在bgRFC中,它呢博得了优化。bgRFC中之初的定义是会调剂在相同华应用服务器上以运转的外向调度程序的无限酷数目,也会见调剂全部RFC调度程序可用之顶大连接数。这个限制会维护当地的Gateway使之不至于过载。

每个发送系统的相的活泼调度程序数量与其的极致大连接数也是只是配置的,因此对此destination的Gateway也存在过载保护。

性能的影响:新bgRFC落实之优化在高负荷、多靠之状态下特别明显。首坏运行的时光,线性对数可伸缩性(a
linear logarithmical
scalability)的RFC数据处理成可能(视系统兼容性而定)。

函数队排的政工特性使得,在拍卖单独的单元时,bgRFC不极端好获得斐然的属性提升,但是当应用还多或者再次快之硬件的时段,则可以肯定提升吞吐量。限制因素会是数据库的特性及这些单元的处理速度。

另外,新的API也是优化的一律有些。一些剩余的函数被移除,某些老的API也不再采取。这使得相关的做事越平缓和有效率,减少支持组织与开发集团的工作量。

再次多信息:

双重多关于bgRFC的音, 请看:

  • bgRFC:
    配置

  • bgRFC:
    管理

  • bgRFC:
    编程

地方数据列:LDQ

地面数据列(Local Data Queue
)是一律种植特别的RFC通信。在这种以情况下,系统非见面再接再厉发送数据。相反,根据拉取规则,系统会管数量存储于本土,直到被表面系统调用(比如移动装备)。

LDQ可以取代原先是因为qRFC在不发送场景下提供的法力(qRFC No
Send)。相比之下它提供了再度有效率的数据模型。

双重多内容:

Local Data Queue
(LDQ)

名词对照

scheduler:调度程序

outbound  queue:外于行

inbound queue:内于行

 

系文章:ABAP
RFC远程调用

 

 

Post Author: admin

发表评论

电子邮件地址不会被公开。 必填项已用*标注