问题场景:
页面login.html 登陆后跳转页面admin.html
这时禁止浏览器或者手机返回按键退回页面login.html
但其他页面支持前进、后退
操作方法可能有多种,例如可能设置个全局变量bClick := true ;然后在OnBackButton事件触发时判断TIWResyncInfo.FormName页面是否允许后退。
TIWResyncInfo = record CurrentTrackId: Cardinal; SubmittedTrackId: Cardinal; FormName: string; FormClassName: string; ExecuteForm: Boolean; SetActiveForm: Boolean; RecreateActiveForm: Boolean; Handled: Boolean; end;
或者可以在OnRewriteURL中判断ARewriteURL包含页面名称和参数。
在这里举一种最简单的方法,操作步骤:
1、设置BackButtonOptions-Mode属性bmEnable,即默认不自动添加任何防止后退的代码。
Mode有四个选项:(bmInterceptGlobal, bmInterceptForm, bmEnable, bmDisableCompat)
默认选项bmDisableCompat 使用兼容旧版的处理方法防止后退。
选择bmInterceptGlobal时IntraWeb将生成JavaScript代码来防止后退按钮的使用。
选择bmInterceptForm时IntraWeb将检查IWForm.PreventBackButton产生的后退记录防止退出应用窗体。
选择bmEnable时IntraWeb将不添加何任防止后退的代码。
2、admin.html页面中添加自定义的js禁止后退代码:
procedure TIndexForm.IWAppFormCreate(Sender: TObject); begin //禁止后退 AddToInitProc('history.pushState(null, null, document.URL);'+ 'window.addEventListener("popstate", function () {'+ 'history.pushState(null, null, document.URL);'+ '});'); end;
3、其他相关js代码
// 浏览器回退禁止 function noBack () { // 历史记录栈中记录页数 var numberOfEntries = window.history.length; if (window.history && window.history.pushState) { window.addEventListener('popstate', function() { // 当点击浏览器的 后退和前进按钮 时才会被触发, window.history.pushState('forward', null, ''); window.history.forward(1); }); } // 新弹出页对应 if (numberOfEntries != 1) { // 页面间跳转用 window.history.pushState('forward', null, ''); window.history.forward(1); } }; //从缓存中获取上一个页面的url,并跳转 window.location.replace(document.referrer); 使用replace() 方法不会在 History 对象中生成一个新的记录。
再讲下页面的登陆和登出
1、登陆时
UserSession.UserID := DMDataMain.FDQuery1['name']; //绑定用户name
UserSession.Time:= IntToStr(DateTimeToUnix(now) - 8 * 60 * 60); //记录时间戳
WebApplication.Response.Cookies.AddCookie('uid', userid, '', Now+1); //写Cookie
2、登出
WebApplication.Response.Cookies.RemoveCookie('uid',''); //删除Cookie
WebApplication.GoToURL('login.html'); //转跳登陆面面
WebApplication.CallBackResponse.AddJavaScriptToExecuteAsCDATA(js);
3、关于session和cookie
session是服务器端的机制,cookie是浏览器端的机制。
Session是把用户的数据写到服务端独占的session中。Cookie是把用户的数据写到用户的当前浏览器中。
通过session可以管理/跟踪会话,可以在用户登录的时候,把用户的登陆信息放进session里面,并在一些内部页面校验是否是当前的session ,以确保当前用户不是游客,并且拥有更多的权限。
例如:添加到购物车,支付购买等。并且通常情况下我们只设置一个session
所以,用户登录时可以把用户信息保存到session域里面。
当你浏览商品,点击购买会提示你还没有登陆,直到登陆后,你的session才开始跟踪你的浏览记录,你才拥有购买的权限。session是保存在服务器的所以相对比较安全。
由于关闭浏览器不会导致session被删除,迫使服务器为seesion设置了一个失效时间,当距离客户端上一次使用session的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把session删除以节省存储空间。
intraweb有自己的全局对象GSessions,使用它的属性GSessions.GetCount,就可以获得session总数。用这个属性可以完成统计访问用户总数,控制用户数量,可以为每个session编序号等功能。
cookie的内容主要包括:名字,值,过期时间,路径和域。若不设置过期时间,则表示这个
cookie的生命期为浏览器会话期间,关闭浏览器窗口,cookie就消失。
在 IW.HTTP.Cookie 单元提供有两个相关类: THTTPCookie、TCookieList; 另外 IWServerController 还有一个 CookieOptions 选项。
读取 Cookie 通常需要Timer定时触发,例如:
procedure TIndexForm.IWTimer1AsyncTimer(Sender: TObject; EventParams: TStringList); var userid:string; begin IWTimer1.Enabled := False; userid := WebApplication.Request.CookieFields.Values['uid']; if userid = '' then WebApplication.GoToURL('login.html') else WebApplication.ShowMessage('用户已登陆,无需要重复登陆!'); end; {遍历 Cookie} procedure TIWForm1.IWButton1Click(Sender: TObject); var str: string; begin for str in WebApplication.Request.CookieFields do IWMemo1.Lines.Add(str); end;
上面介绍了session与cookie两者之间的关系,简单来说:Session放在服务器端。当浏览器关闭就会清空。
Session时间不宜设置过长,否则大量占用服务器内存。Cookie适合长时间保存,在登出时被清除。
验证用户是否登录的逻辑:
1)用户密码登录时,在后台的记住Session
2)如果用户保存登录密码,则记住Cookie,否则把当前用户的Cookie设置为空;
3)每次用户需要向后台进行请求时,进行状态检验:
Session是否存在?若存在,则继续进行请求操作,并将Session的有效时间重新设置一次;
若不存在,则判断cookie是否存在?若存在,使用该cookie完成自动登录,即完成了一次1);
若不存在,则页面重定向到登录页面。
IntraWeb实现方案:
1)、首先在UserSession单元添加一个变量UserID用来标记登陆状态,然后在首页判断UserID是否为空,为空时跳转登陆界面。大于空时用UserID查询数据库取回用户名,用户名=Cookie保存的用户名时进行自动登陆。
if WebApplication.Request.CookieFields.Values['UserID'] = '' then
UserName := WebApplication.Request.CookieFields.Values['UNmae'];
2)、用户登陆成功后向UserID写入标识
UserID := '101';
WebApplication.Response.Cookies.AddCookie('UserID', '101', '', -1);
WebApplication.Response.Cookies.AddCookie('UNmae', 'mingyi', '', -1);
3)、用户选择记住密码时,将密码使用AES加密并保存到Cookie
加密建议使用CnAES单元跨平台通用性好
str := AESEncryptEcbStrToHex(pw,key); //加密
pw := AESDecryptEcbStrFromHex(str,key) //解密
WebApplication.Response.Cookies.AddCookie('PassWord', pw, '', -1)
4)、读取IW_AppName Session,通过用户操作记录判断延长Session过期时间
WebApplication.Request.CookieFields.Values['IW_AppName']);
5)、用户注销登陆时将Session UserID设为空,并删除Cookie记录
UserID := '';
WebApplication.Response.Cookies.RemoveCookie('UserID', '');