ASIHTTPRequest系列(四):Cookies

本文详细介绍了如何在Web开发中使用Cookies技术实现用户免登录功能和存储用户状态信息,包括服务器端Session的使用和客户端Cookies的存取,以及如何在不同页面间传递sessionid,同时提供了针对iPhone客户端的实现案例。

六、使用 Cookies

Cookies 是重要的服务器状态保持策略。Web 服务器常使用 Cookies 技术来实现用户免登录功能和存储用户状态信息。ASIHTTPRequest 支持客户端 Cookies 的存取。

1、服务器端

Session 是服务器端技术,虽然 Cookies 是保存在客户端的。因此我们需要一个服务器端环境。打开 Eclipse,新建 Web 工程,随便写几个简单的 jsp 页面:

<%@ page contentType = "text/html; charset=GBK" %>

< html >

< head >

<%

String lastUrl=(String)request.getParameter( "lastUrl" );

%>

< title > login.jsp </ title >

<!--meta http -equiv ="Content-Type" content="text/html ; charset =iso -8859-1"-->

<!--meta http -equiv ="Content-Type" content="text/html ; charset =gb2312"-->

</ head >

< FORM name = "form1" METHOD = "POST" ACTION = "LoginServlet" >

< p >< input name = "username" type = "text" value = "" >< br >

< p >< input name = "pass" type = "text" value = "" > < br >

< p >< input name = "ok" type = "submit" value = " 提交 " >

< p >< input name = "lastUrl" type = "text" value = " <%= lastUrl %> " >

</ form >

</ html >

这是login.jsp,仅仅有一个用户登录表单。因为在 Web 中,往往只有经过合法登录的用户才需要保持状态。

<%@ page contentType = "text/html; charset=GBK" %>

< html >

< head >

<%

String uid=(String )session.getAttribute( "uid" );

String sessionid=(String)session.getId(); // 获取 sessionid

String lastUrl= "index.jsp" ;

if (uid== null ){

%>

< jsp:forward page = "login.jsp" >

< jsp:param name = "lastUrl" value = "index.jsp" />

</ jsp:forward >

<% %>

< title > index.jsp </ title >

<!--meta http -equiv ="Content-Type" content="text/html ; charset =iso -8859-1"-->

<!--meta http -equiv ="Content-Type" content="text/html ; charset =gb2312"-->

</ head >

< body >

hello <%= "," +uid+ "!" %>

< p >

session id= <%= sessionid %>

< p >

< a href = "second_page.jsp" > goto> > </ a >

</ body >

</ html >

这个是 index.jsp 页面,头部加入了一段 java 代码,要求用户必需登录,否则会自动转向登录页面。另外还把本页 URI 作为请求参数 lastUrl ,这样在登录成功后,会自动跳转到等路前请求的页面。

<%@ page contentType = "text/html; charset=GBK" language = "java" %>

< html >

< head >

<%

String uid=(String )session.getAttribute( "uid" );

String sessionid=(String)session.getId(); // 获取 sessionid

if (uid== null ){

%>

< jsp:forward page = "login.jsp" >

< jsp:param name = "lastUrl" value = "second_page.jsp" />

</ jsp:forward >

<% %>

< title > second page </ title >

<!--meta http -equiv ="Content-Type" content="text/html ; charset =iso -8859-1"-->

<!--meta http -equiv ="Content-Type" content="text/html ; charset =gb2312"-->

</ head >

< body >

seconde page <%= "," +uid+ "!" %>

< p >

session id= <%= sessionid %>

</ body >

</ html >

这个是 second_page.jsp 页面。跟 index.jsp 的意思差不多,只不过想演示一下 sessionid 在多个页面中的传递。

public class LoginServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

String username=request.getParameter( "username" );

String pass=request.getParameter( "pass" );

String lastUrl=request.getParameter( "lastUrl" );

if ( "" .equals(username))

username= null ;

if ( "" .equals(pass))

pass= null ;

boolean loginSuccess= false ;

PrintWriter out=response.getWriter();

if (username!= null && pass!= null ){

loginSuccess= true ;

}

if (loginSuccess){

// 获取 session ,如果 request  session id 不存在,则新建

HttpSession session=request.getSession();

// 不设置 MaxInactiveInterval ,则浏览器一关闭就过期

// session.setMaxInactiveInterval(12*60*60);

session.setAttribute( "uid" ,username);

// 重写 url ,带上 session id

 

String redirectUrl;

if (lastUrl!= null && ! "" .equals(lastUrl)){

redirectUrl=response.encodeURL(lastUrl);

} else {

redirectUrl=response.encodeURL( "index.jsp" );

}

System. out .println( "redirectUrl :" +redirectUrl);

//  forward ,不要用 redirect 。因为后者是服务端转发,没有客户端请求,不会发送 cookie

RequestDispatcher rd=request.getRequestDispatcher(redirectUrl);

rd.forward(request, response);

} else {

// 获取 session ,但 request  session id 不存在时,不新建

HttpSession session=request.getSession( false );

if (session!= null )

session.invalidate(); // 使 session 失效

out.println( "login failed  " );

}

}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

doGet(request,response);

}

这是 servlet,用于用户登录。这里我偷了个懒,只要用户名不为空,我们就通过验证,仅仅为了演示。需要注意的就是两点:

¥  1、response.encodeURL(),这个方法服务器会检测客户端是否支持接收Cookies,如果客户端(比如IE)禁用了Cookies,则服务器会通过重写URL 的方式向客户端发送 sessionid。比如,客户端请求 index.jsp 页面,encodeURL()之后服务器会把 URL 地址改写为:index.jsp;jsessionid=FC076B0E1F0763CFE7BFAFEBA2E0287C

¥  2、页面转发。页面跳转有多种方式。比如 request.sendRedirect。在servlet中,千万不要使用 sendRedirect ,这样会使用服务器跳转,servlet 会把原来的 request 参数和 attributes 全部抛弃(包括 Cookies)。所以sendRedirect 之前和之后的请求使用的不是同一个sessionid。因此在servlet 中,我们采用的是 RequestDispatcher.forward()方法,它是客户端跳转,即服务器会让客户端(浏览器)重新请求另一个地址来转发,保证 session 状态不被丢失。

进行测试,打开浏览器,访问 http://localhost:8080/test/second_page.jsp ,页面会自动跳到 login.jsp。因为 java 脚本检测不到用户的 session 信息(未进行登录)。当你登录后,浏览器返回你原先请求的页面second_page.jsp。

2、iPhone 客户端

ViewController的界面很简单,1个UIWebView,1个UIToolBar,3个UIBarButtonItem:

 

接下来是 ViewController 的 interface 代码:

#import <UIKit/UIKit.h>

#import "ASIHTTPRequest.h"

#define URL @ "http://220.163.103.23/interface/GetSmsList?Accounts=sa&Password=ydtf@95598"

 

 

@interface CokieSessionViewController : UIViewController {

UIBarItem button ,* indexButton ,* secondPageButton ;

UIWebView webView ;

ASIHTTPRequest * request ;

NSURL url ;

  }

@property ( retain , nonatomic ) IBOutlet UIBarItem* button,*indexButton,*secondPageButton;

@property ( retain , nonatomic ) IBOutlet UIWebView* webView;

-( IBAction )login;

-( IBAction )gotoIndexPage;

-( IBAction )gotoSecondPage;

@end

将所有IBOutlet 和 IBAction 对象,在 IB 中建好连接。下面是implement代码:

@implementation CokieSessionViewController

@synthesize button,indexButton,secondPageButton,webView;

- ( void )didReceiveMemoryWarning {

    // Releases the view if it doesn't have a superview.

    [ super didReceiveMemoryWarning ];

}

 

- ( void )viewDidUnload {

    [ super viewDidUnload ];

}

 

 

- ( void )dealloc {

    [ super dealloc ];

}

-( IBAction )login{

BOOL success;

url = [[[ NSURL alloc initWithString : @"http://localhost:8080/test/LoginServlet?username=dd&pass=1" ]autorelease ];

request = [[[ ASIHTTPRequest alloc initWithURL : url autorelease ];

// 设置 cookie 使用策略:使用(默认)

[ request setUseCookiePersistence : YES ];

[ request startSynchronous ];

NSString * html=[ request responseString ];

NSRange range=[html rangeOfString : @"login failed  " options : NSCaseInsensitiveSearch ];

if (range. location == NSNotFound ) { // 如果登录成功

[ webView loadHTMLString : @"login success" baseURL : url ];

} else { // 如果登录失败

[ webView loadHTMLString : @"login failed" baseURL : url ];

}

 

// 获得本地 cookies 集合(在第一次请求时服务器已返回 cookies,

//   虽然其中很可能只有一个cookie: sessionid )

NSArray *cookies = [ request responseCookies ];

// 打印 sessionid

NSHTTPCookie *cookie = nil ;

for (cookie in cookies) {

if ([[cookie name ] isEqualToString : @"JSESSIONID" ]) {

NSLog ( @"session name:%@,value:%@" ,[cookie name ],[cookie value ]);

}

}

}

-( IBAction )gotoIndexPage{

url = [[[ NSURL alloc initWithString : @"http://localhost:8080/test/index.jsp" autorelease ];

request = [[[ ASIHTTPRequest alloc initWithURL : url autorelease ];

// 设置 cookie 使用策略:使用(默认)

[ request setUseCookiePersistence : YES ];

[ request startSynchronous ];

[ webView loadHTMLString :[ request responseString baseURL : url ];

}

-( IBAction )gotoSecondPage{

url = [[[ NSURL alloc initWithString : @"http://localhost:8080/test/second_page.jsp" autorelease ];

request = [[[ ASIHTTPRequest alloc initWithURL : url autorelease ];

// 设置 cookie 使用策略:使用(默认)

[ request setUseCookiePersistence : YES ];

[ request startSynchronous ];

[ webView loadHTMLString :[ request responseString baseURL : url ];

}

@end

编译运行,你可以看到,当点击 index.jsp 和 second_page.jsp 按钮时,webView 中显示的始终是登录界面 login.jsp。因为我们没有获得合法的 session。当然,第一次请求始终可以获得一个 sessionid,然而和登录后的sessionid 不一样,这个 sessionid中不保存任何用户信息。

而点击 login 按钮后,再来点击那两个按钮,则可以显示相应的页面。因为服务器已经在那个sessionid 所对应的session 中放入了用户的ID。我们只需在对应的 jsp 页面中检测用户ID 就可知道用户是否已登录。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值