您的位置:首页 > 其它

RESTful Web Service 的安全(token 认证方式)以及性能

2013-11-19 21:59 771 查看
可扩展性(scalability)和可用性(availability)

custom token authentication

使用一个独一无二的标志,来标示每一次的数据请求。

这个标志有两种用法:1.它可以作为URI的 2.它可以加入到HTTP的请求头中。

@Path("/users/token={token}")

public class UsersResource {

@GET

@Produces("application/xml")

public String getXML(@PathParam("token") String token) {

if (AuthenticationService.authenticate(token)) {

return UserBO.getAllXML();

} else {

throw new WebApplicationException(401);

}

}

}

先检验URI中的标志——Token,如果token变量未通过验证,返回401错误,即未授权。

HTTP basic authentication





即在HTTP请求头中加入一个Authorization: Basic QWxhZGRpbjpvcGVulHNIc2FtZQ==域,就相当于一个证书。对于浏览器而言,会把证书放入缓存中,这样就不必每次都要输入用户名和密码。但这样会导致越权访问,此时由于存在缓存,所以Web Service很难区分请求是否授权。

而且用户名和密码是用Base64 encoding编码的,这个很容易破解,解决这个问题,我们可以用HTTPS(SSL)协议代替HTTP协议。

如果用浏览器访问但没有加入对应的证书,浏览器会出现一个对话框,要求你输入用户名和密码,当用户输入完后,浏览器会再次发送求情。浏览器对401错误会自动处理。

如果使用其他的客户端,则会收到一个401错误。

也可以在刚开始的时候就设置好HTTP请求头,这样就不用每次都输入证书了。

...

HttpClient client = new HttpClient();

client.getState().setCredentials(new AuthScope("www.restfuljava.com",

443, "realm"), new UsernamePasswordCredentials("username",

"password"));

GetMethod get = new GetMethod("http://www.restfuljava.com/webservice

/users");

get.setDoAuthentication(true);

client.executeMethod(get);

...

不过,这样一来,该客户端就只能用于访问证书对应的网站。

OAuth认证方式。

允许第三方访问用户数据,只通过授权验证方式,即每次访问不需要提供用户名及密码。需要为该认证方式提供另外一个独立的Web Service。

如果不用这种方式,如果一个服务提供者想要别人来使用自己的服务,那就必须向使用者提供相应的证书。

OAuth和OpenID是不同的两种协议。OpenID是指,使用同一个证书,访问不同的网络应用。

性能

简单来说,RESTful web service的性能是由web框架决定的。

High availability意味着0或者最低的运行故障时间。对于一个复杂的web结构,达到0运行故障时间是不可能的。有时候我们不得不关掉整个系统,这是不可避免的。

对于如何减少系统故障运行时间最常用的方法就是,硬件冗余,即当一个机器出了问题,停止工作,另外一个机器会接替他的工作。

本节将通过一个示例来介绍如何访问RESTful服务,该示例中,我们通过访问Flickr的REST API返回图片信息,有关Flickr的API大家可以访问http://flickr.com/services/api/查看。开始使用之前需要在http://flickr.com/services/api/keys/申请一个API
Key,如图12-13所示。


(点击查看大图)图12-13
编写一个简单的用户界面,供用户输入搜索主题,如下面的示例代码所示:

XAML
<StackPanel x:Name="LayoutRoot" Background="White">
<StackPanel Orientation="Horizontal">
<TextBox x:Name="txtTopic" Width="300" Height="30"
Margin="10"/>
<Button x:Name="btnSearch" Content="搜 索"
Width="100" Height="30" Margin="5"/>
</StackPanel>
<Image x:Name="imgTarget" Margin="20"/>
</StackPanel>

在"搜索"Button控件单击事件中调用Flickr的REST API,访问RESTful服务并无特别方式,只要发起一个基于HTTP的请求即可,可以使用WebClient或者后面将要介绍的HttpWebRequest,然后对请求的数据做处理,如下面的示例代码所示:

C#
void btnSearch_Click(object sender, RoutedEventArgs e)
{
String apiKey = "3b6ed657779c5c27bb05e73b551d0e7e";
String url = String.Format("
http://api.flickr.com/services/rest/?method=
flickr.photos.search&api_key={1}&text={0}",
txtTopic.Text, apiKey);

WebClient client = new WebClient();
client.DownloadStringCompleted +=
new DownloadStringCompletedEventHandler
(OnFlickrDownloadStringCompleted);
client.DownloadStringAsync(new Uri(url));
}

void OnFlickrDownloadStringCompleted(object sender,
DownloadStringCompletedEventArgs e)
{
if (e.Error != null)
{
return;
}

string result = e.Result;
}

运行程序后,在Visual Studio中使用XML Visualizer查看返回的结果,如图12-14所示。



(点击查看大图)图12-14
可以看到返回的结果是一个标准的、且不复杂的XML文档。对于该XML的处理有很多种方法,可以使用Silverlight 2中操作XML的API或者使用LINQ to XML。现在定义一个业务类来对应XML返回的结果,因为我们最终需要的是图片的URL值,如下面的示例代码所示:

C#
public class FlickrPhoto
{
public String Id { get; set; }
public String Owner { get; set; }
public String Secret { get; set; }
public String Server { get; set; }
public String Farm { get; set; }
public String Title { get; set; }

public String ImageUrl
{
get
{
return String.Format
("http://farm{0}.static.flickr.com/{1}/{2}_{3}.jpg",
Farm, Server, Id, Secret);
}
}
}

该FlickrPhoto 类的ImageUrl属性通过其他几个属性组合而成,大家可以参考Flickr API的有关文档。现在重新修改OnFlickrDownloadStringCompleted事件,并添加两个全局变量Photos和ImageNumber,使用LINQ to
XML实现XML结果与定义的业务类之间的映射,如下面的示例代码所示:

C#
IEnumerable<FlickrPhoto> Photos;
int ImageNumber = 0;

void OnFlickrDownloadStringCompleted(object sender,
DownloadStringCompletedEventArgs e)
{
XDocument xmlPhotos = XDocument.Parse(e.Result);
if (e.Error != null ||
xmlPhotos.Element("rsp").Attribute("stat").Value == "fail")
{
return;
}

Photos = from photo in xmlPhotos.Element("rsp").
Element("photos").Descendants().ToList()
select new FlickrPhoto
{
Id = (String)photo.Attribute("id"),
Owner = (String)photo.Attribute("owner"),
Secret = (String)photo.Attribute("secret"),
Server = (String)photo.Attribute("server"),
Farm = (String)photo.Attribute("farm"),
Title = (String)photo.Attribute("title"),
};

FlickrPhoto p = Photos.Skip(ImageNumber).First();
BitmapImage bitmap = new BitmapImage();
bitmap.UriSource = new Uri(p.ImageUrl);
this.imgTarget.SetValue(Image.SourceProperty, bitmap);
}
}

运行程序后,输入查询条件,可以看到效果如图12-15所示。



(点击查看大图)图12-15
根据搜索的结果,应该是一个图片的集合,但现在仅仅显示一张图片,接下来实现单击图片时,显示下一张图片,在Image控件的MouseLeftButtonDown事件中实现,如下面的示例代码所示:

C#
void imgTarget_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (Photos == null) return;
if (ImageNumber >= Photos.Count()) ImageNumber = 0;


FlickrPhoto p = Photos.Skip(ImageNumber).First();

BitmapImage bitmap = new BitmapImage();

bitmap.UriSource = new Uri(p.ImageUrl);

this.imgTarget.SetValue(Image.SourceProperty, bitmap);

ImageNumber++;

}
现在再单击图片时,将会继续显示下一张。通过上面的示例可以看到,调用RESTful服务与调用其他服务并没有什么特别的地方,仅仅是使用WebClient或HttpWebRequest发起请求,并针对请求结果进行处理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐