下面是Portal消息處理的步驟:
1.客戶端發送請求
如果未登陸,則沒有Cookie,
如果是登陸頁面,則會生成Cookie並帶上.
如果已登陸,則已有Cookie,直接帶上.
2.服務端Global中對信息的處理
--1.在Global的Application_BeginRequest事件中將站點信息保存在HttpContext變量SiteSetting中,並根據請求的參數 TabIndex和TabId得到門戶配置信息並保存在HttpContext變量PortalSetting中;
// 如果不是DesktopDefault頁面也要執行這個函數,這樣就是多余的了,不是嗎?
protected void Application_BeginRequest(Object sender, EventArgs e)
{
int tabIndex = 0 ;
int tabId = 1 ;
// Get TabIndex from querystring
// 在當前請求字符中獲取tabIndex的值
if (Request.Params[ " tabindex " ] != null )
{
tabIndex = Int32.Parse(Request.Params[ " tabindex " ]);
}
// Get TabID from querystring
// 從當前請求字符中獲取tabId的值
if (Request.Params[ " tabid " ] != null )
{
tabId = Int32.Parse(Request.Params[ " tabid " ]);
}
// Build and add the PortalSettings object to the current Context
// 建立並添加PortalSettings(門戶站點設置對像)到HttpContext對像中
Context.Items.Add( " PortalSettings " , new PortalSettings(tabIndex, tabId));
// Retrieve and add the SiteConfiguration DataSet to the current Context
// 將站點設置信息(數據集形式)添加到HttpContext中
HttpContext.Current.Items.Add( " SiteSettings " , Configuration.GetSiteSettings());
try
{
if (Request.UserLanguages != null )
Thread.CurrentThread.CurrentCulture =
CultureInfo.CreateSpecificCulture(Request.UserLanguages[ 0 ]);
else
// Default to English if there are no user languages
Thread.CurrentThread.CurrentCulture = new CultureInfo( " en-us " );
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
}
catch
{
Thread.CurrentThread.CurrentCulture = new CultureInfo( " en-us " );
}
}
--2.在Application_AuthenticateRequest中根據cookie等信息驗證用戶身份並授與用戶角色;
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if (Request.IsAuthenticated == true )
{
String[] roles;
// 不存入Cookie每次都從數據庫中讀取
UsersDB user = new UsersDB();
roles = user.GetRoles(User.Identity.Name);
// Create a string to persist the roles
// 以字符串的形式存儲用戶角色信息用";"分隔,一個用戶的多個角色
String roleStr = "" ;
foreach (String role in roles)
{
roleStr += role;
roleStr += " ; " ;
}
// Create a cookie authentication ticket.
// 創建身份角色驗證的憑據
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1 , // version 版本
Context.User.Identity.Name, // user name cookie 名
DateTime.Now, // issue time 發布日期
DateTime.Now.AddHours( 1 ), // expires every hour 過期日期
false , // don't persist cookie 持久性(false)
roleStr // roles 用戶定義的數據初始化(";"分隔的角色字符串)
);
// Add our own custom principal to the request containing the roles in the auth ticket
// 從 GenericIdentity 和角色名稱數組(GenericIdentity 表示的用戶屬於該數組)初始化 GenericPrincipal 類的新實例。
Context.User = new GenericPrincipal(Context.User.Identity, roles);
}
}
3.在頁面中導入相應的頁面內容
--1.如果是DesktopDefault.aspx頁面,則檢查用戶權限,如果有,則根據PortalSettings,找到相應的模塊並顯示在左中右三個面板中,並設定題頭的標簽.(這樣一來,如果手動在地址欄輸入TabIndex和TabId,顯示時題頭與模塊可能會不一致,便不影響權限控製);如果沒有則轉向其它頁面.
// 不過如果手動在地址欄輸入TabIndex和TabId,顯示時題頭與模塊可能會不一致.
private void InitClass()
{
// 從HttpContext中獲取全局設置對像
PortalSettings portalSettings = (PortalSettings) HttpContext.Current.Items[ " PortalSettings " ];
// 設置標題欄
pageTitle.Text = portalSettings.PortalName;
// Ensure that the visiting user has access to the current page
// 當當前用戶的角色不在當前活動標簽的可訪問角色中時,重定向到訪問錯誤頁
if (PortalSecurity.IsInRoles(portalSettings.ActiveTab.AuthorizedRoles) == false )
{
Response.Redirect( " ~/Admin/AccessDenied.aspx " );
}
// Dynamically inject a signin login module into the top left-hand corner
// of the home page if the client is not yet authenticated
// 判斷是否顯示登陸信息(當用戶未驗證且顯示頁面為第一頁時)
if ((Request.IsAuthenticated == false ) && (portalSettings.ActiveTab.TabIndex == 0 ))
{
LeftPane.Controls.Add(Page.LoadControl( " ~/DesktopModules/SignIn.ascx " ));
LeftPane.Visible = true ;
}
// Dynamically Populate the Left, Center and Right pane sections of the portal page
// 當前標簽下的模塊數大於0時,分別在左中右三個方塊中顯示當前標簽下的模塊
if (portalSettings.ActiveTab.Modules.Count > 0 )
{
// Loop through each entry in the configuration system for this tab
// 在當前標簽的模塊列表中依次讀取模塊
foreach (ModuleSettings _moduleSettings in portalSettings.ActiveTab.Modules)
{
// 在頁面中找到存放指定控件的板塊(左中右)
Control parent = Page.FindControl(_moduleSettings.PaneName);
// If no caching is specified, create the user control instance and dynamically
// inject it into the page. Otherwise, create a cached module instance that
// may or may not optionally inject the module into the tree
// 如果控件的緩存時間為0
if ((_moduleSettings.CacheTime) == 0 )
{
// 構造用戶控件
PortalModuleControl portalModule = (PortalModuleControl) Page.LoadControl(_moduleSettings.DesktopSrc);
portalModule.PortalId = portalSettings.PortalId;
portalModule.ModuleConfiguration = _moduleSettings;
// 在指定板塊中加載控件
parent.Controls.Add(portalModule);
}
else
{
CachedPortalModuleControl portalModule = new CachedPortalModuleControl();
portalModule.PortalId = portalSettings.PortalId;
portalModule.ModuleConfiguration = _moduleSettings;
parent.Controls.Add(portalModule);
}
// Dynamically inject separator break between portal modules
// 加入控件之間的分隔符
parent.Controls.Add( new LiteralControl( " < " + " br " + " > " ));
// 將存放控件的板塊置為可見
parent.Visible = true ;
}
}
}
--2.如果是其它頁面(基本是一些編輯頁面,明細表頁面),則在頁面的Load事件中判斷權限,並決定顯示頁面內容,還是轉向其它頁面.
private void Page_Load( object sender, System.EventArgs e)
{
// 所屬模塊Id
moduleId = Int32.Parse(Request.Params[ " Mid " ]);
// 驗證用戶是否可以修改指定模塊
if (PortalSecurity.HasEditPermissions(moduleId) == false )
{
Response.Redirect( " ~/Admin/EditAccessDenied.aspx " );
}
// 項Id
if (Request.Params[ " ItemId " ] != null )
{
itemId = Int32.Parse(Request.Params[ " ItemId " ]);
}
if (Page.IsPostBack == false )
{
if (itemId != 0 )
{
// 獲取指定itemId的公告內容
AnnouncementsDB announcementDB = new AnnouncementsDB();
SqlDataReader dr = announcementDB.GetSingleAnnouncement(itemId);
dr.Read();
int dbModuleID = Convert.ToInt32(dr[ " ModuleID " ]);
if (dbModuleID != moduleId)
{
dr.Close();
Response.Redirect( " ~/Admin/EditAccessDenied.aspx " );
}
TitleField.Text = (String) dr[ " Title " ];
MoreLinkField.Text = (String) dr[ " MoreLink " ];
MobileMoreField.Text = (String) dr[ " MobileMoreLink " ];
DescriptionField.Text = (String) dr[ " Description " ];
ExpireField.Text = ((DateTime) dr[ " ExpireDate " ]).ToShortDateString();
CreatedBy.Text = (String) dr[ " CreatedByUser " ];
CreatedDate.Text = ((DateTime) dr[ " CreatedDate " ]).ToShortDateString();
dr.Close();
}
else
{
// 默認有效期為一個星期
ExpireField.Text = DateTime.Today.AddDays( 7 ).ToString( " yyyy-MM-dd " );
}
// 存儲上次請求頁Url
ViewState[ " UrlReferrer " ] = Request.UrlReferrer.ToString();
}
}
附:下面這個鏈接是關於DNN頁面生成原理的.我還沒有看DNN,不過我覺得他講的和Portal的原理差不多一樣.
http://www.cnblogs.com/genode/archive/2005/06/05/168235.html