首先对所有的请求进行安全检验和认证,后面会给出对固定的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(); } }