欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Restlet实战(九)访问敏感资源之Digest认证

程序员文章站 2022-07-03 20:53:06
...

首先对所有的请求进行安全检验和认证,后面会给出对固定的URL进行安全认证的情况。对Restlet1.1.5来说,需要借助于Guard类来完成。

 

说一下大概的思路,建立一个Guard,并把它直接attach到Componet,当请求过来以后,会首先路由到这个Guard,如果通过认证,则路由到对应URL的Resource,否则,拦截掉。

 

首先修改Spring的配置文件:

 

	<bean id="component" class="org.restlet.ext.spring.SpringComponent">
		<property name="defaultTarget" ref="guard" />
	</bean>
	
	<bean id="guard" class="com.mycompany.restlet.filter.CustomerGuardFilter"> 
		<property name="next" ref="restRoute"/>
		<property name="secretResolver" ref="customerResolver"/> 
	</bean>
	
	<bean id="customerResolver" class="com.mycompany.restlet.filter.CustomerResolver"/>
	

 

从上述配置文件能看到,我们为SpringComponent的defaultTarget属性配置了一个Guard,当然这个是我们自己customized的一个Guard。而对于这个Guard,则指定其中的两个属性:next和secretResolver,next的意思是,如果通过校验和认证,则路由到下一个restlet实例,而secretResolver则是进行校验的地方。相关代码如下:

 

 

public class CustomerGuardFilter extends Guard {

	public CustomerGuardFilter(Context context, ChallengeScheme scheme, String realm) {
		super(context, scheme, realm);
	}
	
	public CustomerGuardFilter(){
		this(Context.getCurrent(), ChallengeScheme.HTTP_DIGEST, "realm");
	}
	
}

 

public class CustomerResolver extends Resolver<char[]> {

    /**
     * Returns the value that corresponds to the given name.
     */
    @Override
    public char[] resolve(String name) {
        // Could have a look into a database, LDAP directory, etc.
        if ("login".equals(name)) {
            return "secret".toCharArray();
        }

        return null;
    }

}

 

CustomerResolver类里面注释的地方,实际上就是我们在产品环境中从数据库或者LDAPdirectory或者别的地方取出密码的过程,这里,仅仅是为了测试,所以,直接硬编码了。

 

下面我们分别分别使用Restlet和Httpclient提供的API来编写客户端进行测试:

 

1.使用Restlet来测试

 

public static void testClientWithRestlet() {
	Reference reference = new Reference("http://localhost:8080/restlet/resources/customers");
	Client client = new Client(Protocol.HTTP);
	Request request = new Request(Method.GET, reference);

	ChallengeResponse challengeResponse = new ChallengeResponse(ChallengeScheme.HTTP_DIGEST, "login", "secret");
	request.setChallengeResponse(challengeResponse);

	// Send the first request
	Response response = client.handle(request);

	// Complete the challengeResponse object according to the server's data
	Form form = new Form();
	form.add("username", "login");
	form.add("uri", reference.getPath());

	// Loop over the challengeRequest objects sent by the server.
	for (ChallengeRequest challengeRequest : response.getChallengeRequests()) {
		// Get the data from the server's response.
		if (ChallengeScheme.HTTP_DIGEST.equals(challengeRequest.getScheme())) {
			Series<Parameter> params = challengeRequest.getParameters();
			form.add(params.getFirst("nonce"));
			form.add(params.getFirst("realm"));
			form.add(params.getFirst("domain"));
			form.add(params.getFirst("algorithm"));
			form.add(params.getFirst("qop"));
		}
	}

	// Compute the required data
	String a1 = Engine.getInstance().toMd5("login" + ":" + form.getFirstValue("realm") + ":" + "secret");
	String a2 = Engine.getInstance().toMd5(request.getMethod() + ":" + form.getFirstValue("uri"));
	form.add("response", Engine.getInstance().toMd5(a1 + ":" + form.getFirstValue("nonce") + ":" + a2));
	challengeResponse.setCredentialComponents(form);

	// Send the completed request
	request.setChallengeResponse(challengeResponse);
	response = client.handle(request);
}

 

 2. 使用Httpclient测试

 

public static void testClientWithHttpclient() throws Exception{
	HttpClient client = new HttpClient();
	client.getState().setCredentials(
		new AuthScope("localhost", 8080, "realm"),
		new UsernamePasswordCredentials("login", "secret"));

	List<String> authPrefs = new ArrayList<String>();
	authPrefs.add(AuthPolicy.DIGEST);
	client.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);

	GetMethod httpget = new GetMethod("http://localhost:8080/restlet/resources/customers");

	try {
		int status = client.executeMethod(httpget);
		// print the status and response
		System.out.println(status);
		System.out.println(httpget.getStatusLine());
		System.out.println(httpget.getResponseBodyAsString());
	} finally {
		// release any connection resources used by the method
		httpget.releaseConnection();
	}            
}