对于没有session的客户端, 比如基于httpClient的http Invoker实现,那么就只能使用basic认证了(摘要认证流程一致),基于spring security自带的contact 示例
<http>元素配置如下
1 2 3 4 5 |
<http pattern="/remoting/**" use-expressions="false"> <intercept-url pattern="/**" access="ROLE_USER"/> <csrf disabled="true"/> <http-basic/> </http> |
spring mvc 的配置如下:
1 2 3 4 |
<bean name="/ContactManager-httpinvoker" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter"> <property name="service" ref="contactManager"/> <property name="serviceInterface" value="sample.contact.ContactManager"/> </bean> |
在web.xml中声明:
1 2 3 4 5 6 7 8 9 |
<servlet> <servlet-name>remoting</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>remoting</servlet-name> <url-pattern>/remoting/*</url-pattern> </servlet-mapping> |
客户端的spring上下文配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 |
<bean id="httpInvokerProxy" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean"> <property name="serviceInterface"> <value>sample.contact.ContactManager</value> </property> <property name="serviceUrl"> <value>http://${serverName}:${httpPort}${contextPath}/remoting/ContactManager-httpinvoker</value> </property> <property name="httpInvokerRequestExecutor"> <ref local="httpInvokerRequestExecutor"/> </property> </bean> <bean id="httpInvokerRequestExecutor" class="sample.contact.BasicAuthenticationHttpInvokerRequestExecutor"/> |
BasicAuthenticationHttpInvokerRequestExecutor在老的spring security版本中有实现, 现在需要自己实现了。源码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
public class BasicAuthenticationHttpInvokerRequestExecutor extends SimpleHttpInvokerRequestExecutor { @Override protected void prepareConnection(HttpURLConnection connection, int contentLength) throws IOException { super.prepareConnection(connection, contentLength); Authentication auth = SecurityContextHolder.getContext() .getAuthentication(); if ((auth != null) && (auth.getName() != null) && (auth.getCredentials() != null)) { String base64 = auth.getName() + ":" + auth.getCredentials().toString(); connection.setRequestProperty("Authorization", "Basic " + new String(Base64.encodeBase64(base64.getBytes()))); if (logger.isDebugEnabled()) { logger.debug("HttpInvocation now presenting via BASIC authentication SecurityContextHolder-derived: " + auth.toString()); } } else { if (logger.isDebugEnabled()) { logger.debug("Unable to set BASIC authentication header as SecurityContext did not provide valid Authentication: " + auth); } } } } |
Main 方法如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
public class ClientApplication { private final ListableBeanFactory beanFactory; public ClientApplication(ListableBeanFactory beanFactory) { this.beanFactory = beanFactory; } public void invokeContactManager(Authentication authentication, int nrOfCalls) { Map<String, ContactManager> contactServices = this.beanFactory.getBeansOfType( ContactManager.class, true, true); SecurityContextHolder.getContext().setAuthentication(authentication); for (String beanName : contactServices.keySet()) { ContactManager remoteContactManager = contactServices.get(beanName); System.out.println("Calling ContactManager '" + beanName + "'"); List<Contact> contacts = null; for (int i = 0; i < nrOfCalls; i++) { contacts = remoteContactManager.getAll(); } if (contacts.size() != 0) { for (Contact contact : contacts) { System.out.println("Contact: " + contact); } } else { System.out.println("No contacts found which this user has permission to"); } System.out.println(); } SecurityContextHolder.clearContext(); } public static void main(String[] args) { String username = System.getProperty("username", ""); String password = System.getProperty("password", ""); String nrOfCallsString = System.getProperty("nrOfCalls", ""); if ("".equals(username) || "".equals(password)) { System.out .println("You need to specify the user ID to use, the password to use, and optionally a number of calls " + "using the username, password, and nrOfCalls system properties respectively. eg for user rod, " + "use: -Dusername=rod -Dpassword=koala' for a single call per service and " + "use: -Dusername=rod -Dpassword=koala -DnrOfCalls=10 for ten calls per service."); System.exit(-1); } else { int nrOfCalls = 1; if (!"".equals(nrOfCallsString)) { nrOfCalls = Integer.parseInt(nrOfCallsString); } ListableBeanFactory beanFactory = new FileSystemXmlApplicationContext( "client/clientContext.xml"); ClientApplication client = new ClientApplication(beanFactory); client.invokeContactManager(new UsernamePasswordAuthenticationToken(username, password), nrOfCalls); System.exit(0); } } } |
Posted in: Spring Security
Comments are closed.