前言:在应用于集团版客户或SAAS平台服务的业务系统中,流程管理系统需要支持多用户组织模型。其中包括角色数据、流程定义数据和流程实例数据的多用户标识绑定。本文旨在全面描述如何基于SlickOne敏捷开发框架实现上述基础服务功能,形成一个完整的支持多用户查看和维护各自流程数据的管理后台系统。

1. 基础数据的多用户标识

1.1 多用户(公司)数据表

数据库表SysCompany用来存储多用户/多租户的基本信息,字段CompanyID 用来标识后期业务数据的所有者。

1.2 角色/用户数据表

角色用户表统一增加CompanyID字段,用来确定角色和用户属于具体的那一个用户或租户。

1.3. 流程定义数据的多用户标识

数据库表WfProcess增加CompanyID字段,用来标识流程定义属于那一个用户或租户。

1.4. 流程实例数据的多用户标识

所有的流程实例数据,统一增加CompanyID字段,用了标识流程实例数据的拥有者范围。

2. 多站点类型的SSO功能实现

多站点SSO单点登录功能的实现,便于统一整合不同子系统的数据管理和维护;尤其对于平台级别的软件产品,多个子系统的是需要经常频繁操作访问的。所以,一次登录,再次免验证,就非常方便简捷。

2.1 系统环境配置

1) Form 认证方式配置

    <authentication mode="Forms">
<forms loginUrl="http://localhost/sfadmin/Account/Login" protection="All" timeout="240" name=".AuthCookie" />
</authentication>

2) Session 状态存储配置

    <sessionState mode="InProc" customProvider="DefaultSessionProvider" timeout="480">
<providers>
<add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" />
</providers>
</sessionState>

3) MachineKey 配置

<machineKey validationKey="zsdgfdg3FF1B0F88DDF585BA5D35E7BC87E3F0AB47FBBEBD12240DD3BEA2BEAEC4ABA215478658ugfjnhgfnmj3F22AD27E8FAD77DCFEE306219691434908D193A17C1FC8DCE51B71A4AE54920" decryptionKey="ECB6A3AF9ABBF3F16E80685ED68DC74B0B13CCEE538EBBA97D0B893139683B3B" validation="SHA256" decryption="AES" />

4) 登录页面重定向地址

    <add key="FormAuthenticationRedirectUrl" value="http://localhost/sfadmin/Account/Login"/>

2.2 Session 对象操作和访问

用于服务端用户对象的身份信息存储,包括用户ID标识,用户名称,公司ID标识,票据信息和权限数据等。

 /// <summary>
/// 获取登录用户ID
/// </summary>
/// <param name="session"></param>
/// <returns></returns>
public int GetLogonUserID()
{
return (int)Get(WEB_LOGON_USER_ID);
} public int GetLogonCompanyID()
{
return (int)Get(WEB_LOGON_COMPANY_ID);
} /// <summary>
/// 获取登录用户Session的GUID
/// </summary>
/// <param name="session"></param>
/// <returns></returns>
public string GetLogonUserSessionGUID()
{
return Get(WEB_LOGON_SESSION_GUID).ToString();
} /// <summary>
/// 获取登录用户票据
/// </summary>
/// <param name="session"></param>
/// <returns></returns>
public string GetLogonUserTicket()
{
var obj = Get(WEB_LOGON_USER_TICKET);
var ticket = obj != null ? obj.ToString() : string.Empty;
return ticket;
}

2.3 Cookie 对象操作和访问

前端JS脚本访问用户的特定信息,通过Cookie对象获取来实现,大致代码如下:

function getWebLogonUserCookie() {
var name = "SlickOneWebLogonUserDataCookie";
var cookie = getCookie(name);
if (cookie !== undefined) {
var userAccount = $.parseJSON(cookie);
return userAccount;
} else {
return null;
}
} lsm.getWebLogonUserID = function () {
var userAccount = getWebLogonUserCookie();
var userID = userAccount.UserID;
return userID;
} lsm.getWebLogonCompanyID = function () {
var userAccount = getWebLogonUserCookie();
if (userAccount !== null) {
var companyID = userAccount.CompanyID;
return companyID;
} else {
return "";
}
}

2.4 登录验证后的票据存储

用户登录之后,需要将其基本身份信息和关联的角色或权限数据存储下来。而且作为前后端分离的系统,服务端需要使用这些票据数据,前端也需要通过Cookie对象访问用户信息,作为权限控制的审核来源。

 //create form ticket
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(, loginName, DateTime.Now, DateTime.Now.AddMinutes(),
true, userDataContent, FormsAuthentication.FormsCookiePath); string ticString = FormsAuthentication.Encrypt(ticket); //write cookies in response
//SetAuthCookie mark identity status true
HttpContext.Current.Response.Cookies.Add(new HttpCookie("SlickOneWebCookie", ticString));

3. Mvc页面及WebAPI安全访问

3.1 Mvc页面授权访问

页面控制器统一继承于页面基类,基类中重载方法OnActionExecuting(),读取用户身份信息,并存储到Session对象,如果是非授权用户,则跳转到登录页面。代码示例如下:

/// <summary>
/// Authentication Verify When Action Executing
/// </summary>
/// <param name="filterContext"></param>
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
var attr = filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), true);
bool isAnonymous = attr.Any(a => a is AllowAnonymousAttribute);
if (isAnonymous == false)
{
var session = filterContext.HttpContext.Session;
this.SessionManager.SetSession(session); var user = this.SessionManager.GetLogonUser() as WebLogonUser;
if (user == null)
{
var webCookie = base.Request.Cookies["SlickOneWebCookie"];
if (webCookie != null && !string.IsNullOrEmpty(webCookie.Value))
{
var encryptTicket = webCookie.Value;
SaveUserSession(encryptTicket);
}
else
{
//Not a Valid Logon User, Need To Be Login Agagin
var formRedirectUrl = WebConfigurationManager.AppSettings["FormAuthenticationRedirectUrl"].ToString();
string url = string.Format("{0}?ReturnUrl={1}", formRedirectUrl, Request.RawUrl);
filterContext.HttpContext.Response.Redirect(url, true);
}
}
}
base.OnActionExecuting(filterContext);
}

3.2 WebAPI 接口安全访问

WebAPI控制器增加属性过滤器,用于验证是否是授权访问的接口,其中需要从Cookie中读取票据信息,验证审核用户是否是合法授权用户。

/// <summary>
/// check authorizaton information when action executing
/// </summary>
/// <param name="actionContext"></param>
public override void OnActionExecuting(HttpActionContext actionContext)
{
//get authentication cookie from request
var authCookie = actionContext.Request.GetCookie("SlickOneWebCookie");
if (!String.IsNullOrEmpty(authCookie))
{
//decrypted user ticket information
if (ValidateUserTicket(authCookie))
base.OnActionExecuting(actionContext);
else
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
}
else
{
//verify webapi security setting
bool isRquired = (WebConfigurationManager.AppSettings["WebApiSecurityEnabled"].ToString() == "true");
if (isRquired)
{
//check anonymous attribute
var attr = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>();
bool isAnonymous = attr.Any(a => a is AllowAnonymousAttribute); if (isAnonymous)
base.OnActionExecuting(actionContext);
else
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
}
else
{
base.OnActionExecuting(actionContext);
}
}
}

 4. 主界面操作说明

主界面是整个后台数据维护的入口页面,集成了用户基础数据、流程数据、表单数据和其它设置页面。其中流程定义,表单定义都链接到不同的WEB应用程序地址,这些WEB应用程序统一实现SSO要求的FORM认证,统一登录地址等特性。保证一次登录,再次免验证就能访问各子系统的简捷操作。

5. 总结

SlickOne敏捷框架的示例项目,主要包括了基础数据的维护,业务系统集成访问,SSO单点登录实现,MVC页面安全和WebAPI安全访问等功能特性。作为企业级应用系统的开发,可以完全担当软件团队的技术统一框架解决方案。在后期的版本中,依然考虑企业用户的需求,增加和构建功能模块,做到框架软件的可扩展和二次开发。

6. DEMO

  1. 演示地址:http://gc.slickflow.com/sfadmin/
  2. 用户名和密码:admin/123456
  3. 流程设计器:http://gc.slickflow.com/sfd/
  4. 表单设计器:http://gc.slickflow.com/smd/

7. 社区版源代码

SlickOne项目开源地址:

http://github.com/besley/slickone

8. 企业版授权说明

1) Demo仅作为功能演示使用,如需获取产品完整源代码和开发文档,请申请企业版商业授权。

2) QQ群:151650479

3) EMail: sales@ruochisoft.com

9. 参考

1. SlickOne 敏捷开发框架介绍(一)

SlickOne 敏捷开发框架介绍(二) -- 多用户/多租户/SAAS软件基础框架实现的更多相关文章

  1. SlickOne敏捷开发框架介绍(一) -- 基于Dapper, Mvc和WebAPI 的快速开发框架

    前言:在两年前(最初发布时间:2013年1月9日(csdn),当前文章时间2015年11月10日),项目组推出了基于Dapper,Mvc和WebApi的快速开发框架,随着后续Slickflow产品的实 ...

  2. 基于DDD的.NET开发框架ABP实例,多租户 (Saas)应用程序,采用.NET MVC, Angularjs, EntityFramework-介绍

    介绍 基于ABPZERO的多租户 (Saas)应用程序,采用ASP.NET MVC, Angularjs-介绍 ASP.NET Boilerplate作为应用程序框架. ASP.NET MVC和ASP ...

  3. java 快速开发框架平台 二次开发 代码生成器 springmvc SSM后台框架源码

    官网 http://www.fhadmin.org/D 集成安全权限框架shiro  Shiro 是一个用 Java 语言实现的框架,通过一个简单易用的 API 提供身份验证和授权,更安全,更可靠E ...

  4. RDIFramework.NET敏捷开发框架 ━ 工作流程组件介绍

    RDIFramework.NET,基于.NET的快速信息化系统敏捷开发.整合框架,给用户和开发者最佳的.Net框架部署方案. 1.RDIFramework.NET敏捷开发框架介绍 RDIFramewo ...

  5. RDIFramework.NET ━ .NET敏捷开发框架全新发布-最好用的.NET开发框架 100%源码授权

    RDIFramework.NET,基于.NET的快速信息化系统敏捷开发框架.10年沉淀.历经上千项目检验,致力于企业智能化开发,帮助提升软件开发效率.最好用的.NET开发框架,100%源码授权. 1. ...

  6. 如何提高码农产量,基于ASP.NET MVC的敏捷开发框架之移动端开发随笔二

    前言 在前一篇文章中我已经做过开篇,接下来的随笔会详细讲一下我们的开发框架是如何实现的,专业的事由专业的人来讲,以后就由我们的高级码农小李英文名查尔斯和他的师父厂长(因为姓陈,酷爱摄影,我们的文艺片都 ...

  7. RDIFramework.NET敏捷开发框架通过SignalR技术整合即时通讯(IM)

    1.引言 即时通讯(IM)是RDIFramework.NET敏捷开发框架全新提供的一个基于Web的即时通讯.内部聊天沟通的工具.界面美观大方对于框架内部进行消息的沟通非常方便.基于RDIFramewo ...

  8. RDIFramework.NET敏捷开发框架 ━ 工作流程组件Web业务平台

    接前两篇: RDIFramework.NET敏捷开发框架 ━ 工作流程组件介绍 RDIFramework.NET敏捷开发框架 ━ 工作流程组件WinForm业务平台 1.RDIFramework.NE ...

  9. RDIFramework.NET敏捷开发框架Web新增邮件中心实现便捷式的邮件收发

    1.引言 邮件收发在很多业务系统中都有这样的需求,是比较正式和常用的功能.在我们的框架中提供了邮件中心功能模块,集内部邮件的收发.邮件归类.邮件星标的标记.邮件的删除与彻底删除等,邮件中心功能模块界面 ...

随机推荐

  1. Java Web之路(二)Servlet之HttpServletResponse和HttpServletRequest

    HttpServletResponse 1.告诉服务器应用使用UTF-8解析文本的两种方式,告诉客户端要使用什么编码 response.setHeader("content-type&quo ...

  2. 这两天自己模仿写的一个Asp.Net的显示分页方法 附加实体转换和存储过程

    之前自己一直用Aspnetpager控件来显示项目中的分页,但是每次都要拖一个aspnetpager的控件进去,感觉很不舒服,因为现在自己写的webform都不用服务器控件了,所以自己仿照aspnet ...

  3. expect 交互 之双引号较长变量

    交互双引号较长变量  #!/bin/bash RemoteUser=xuesong12 Ip=192.168.1.2 RemotePasswd=xuesong Cmd="/bin/echo ...

  4. Mysql导入脚本失败,提示需要SUPER权限

    1.删除: /*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */ 2.查看增删函数有没有重复 3.删除: set GLOBAL log ...

  5. ARM linux内核启动时几个关键地址【转】

    转自:http://www.cnblogs.com/armlinux/archive/2011/11/06/2396787.html 1.       内核启动地址1.1.   名词解释ZTEXTAD ...

  6. Python学习四|变量、对象、引用的介绍

    变量 变量创建:一个变量也就是变量名,就像a,当代码第一次赋值时就创建了它.之后的赋值将会改变已创建的变量名的值,从技术上讲,Python在代码运行之前先检测变量名,可以当成是最初的赋值创建了变量. ...

  7. COM和.NET的互操作

    组件对象模型的基本知识         基于构件的软件开发日益流行,这里我吧自己在学校时整理的关于COM的一些东西献给大家,供初学者参考.一.组件(COM),是微软公司为了计算机工业的软件生产更加符合 ...

  8. nginx:支持跨域访问

    在http节点中配置: #支持跨域访问 add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Header ...

  9. hdu 1166 线段树(单点增减 区间求和)

    Sample Input1101 2 3 4 5 6 7 8 9 10Query 1 3Add 3 6Query 2 7Sub 10 2Add 6 3Query 3 10End Sample Outp ...

  10. Redux架构

    深入Redux架构   阅读目录 关于redux API 中间件与异步操作 异步操作的基本思路 React-Redux的用法 回到顶部 关于redux 之前写了一篇通过一个demo了解Redux,但对 ...