tag:blogger.com,1999:blog-73550442400073641512024-03-14T10:33:27.591+05:30KUSHAN'S TECH BLOGKushan Jayathilakehttp://www.blogger.com/profile/14972462055058843725noreply@blogger.comBlogger5125tag:blogger.com,1999:blog-7355044240007364151.post-7018949781165163442011-03-15T12:56:00.005+05:302012-07-23T11:59:10.445+05:30Getting started with Spring Security 3 with JBoss and MySQLHi Folks,<br />
<br />
Lets get started.<br />
<br />
You need to download,<br />
<br />
<a href="http://s3.amazonaws.com/dist.springframework.org/milestone/SEC/spring-security-3.1.0.RC1.zip">1. Spring Security Module 3</a><br />
<a href="http://dev.mysql.com/downloads/mysql/5.1.html">2. MySQL 5.1</a><br />
<a href="http://sourceforge.net/projects/jboss/files/JBoss/JBoss-4.2.0.GA/jboss-4.2.0.GA.zip/download">3. JBoss 4.2 GA</a><br />
<br />
<br />
I'm using eclipse as the IDE.<br />
<br />
Create a simple Web Project in eclipse IDE,<br />
<br />
Among the jar files of the Spring Security module you will see a 2 WAR files. open the WAR file spring-security-samples-tutorial-3.0.5.RELEASE.war with WinZIP or WinRAR like tool and copy all the JAR files there to the lib folder of the project.<br />
<br />
Add all the copied JAR files to buildpath.<br />
<br />
First of all you need to create a login page for your web application. create a simple JSP file and name it as login.jsp and paste the following code fragment there.<br />
<br />
<br />
<pre class="Cpp" name="code"><form action="/test/j_spring_security_check" method="post">
Username : <input type="text" name="j_username" id="j_username">
Password : <input type="password" name="j_password" id="j_password">
<input type="submit" value="Submit">
</form>
</pre>
<br />
Remember that,<br />
<br />
1. j_spring_security_check is the URL you need to call as the action (/test is the context root of your web application).<br />
<br />
2. Name of your username and the password fields should be j_username and j_password<br />
<br />
Once the user been authenticated, we need to forward the user to a different page. so lets create another jsp file for that and name it as user_authenticated.jsp<br />
<br />
You are going to authorize the user according to their user roles, so here I have created separate JSPs to show some user role level authorization. my user roles are,<br />
<br />
1. ROLE_SUPERVISOR (supervisor.jsp)<br />
2. ROLE_USER (user.jsp)<br />
3. ROLE_TELLER (teller.jsp)<br />
<br />
Now let's configure Spring.<br />
<br />
You will need 2 xml files to hold Spring Security info and the Datasource info to the MySQL DB. See below,<br />
<br />
1. applicationContext-security.xml (Your Spring Security configuration file)<br />
2. applicationContext-db.xml (Your datasource configuration file)<br />
<br />
Create above 2 files in your WEB-INF directory.<br />
<br />
<u><b>applicationContext-security.xml</b></u><br />
<br />
Simply you can copy the same file from the tutorial war file that I have mentioned above, and modify its contents as I have described below.<br />
<br />
<pre class="Cpp" name="code"><http use-expressions="true">
<intercept-url pattern="/user_authenticated.jsp" access="isAuthenticated()" />
<intercept-url pattern="/supervisor.jsp" access="hasRole('ROLE_SUPERVISOR')" />
<intercept-url pattern="/teller.jsp" access="hasRole('ROLE_TELLER')" />
<intercept-url pattern="/user.jsp" access="hasRole('ROLE_USER')" />
<intercept-url pattern="/**" access="permitAll" />
<form-login login-page='/login.jsp'/>
<logout />
<remember-me />
<!--
Uncomment to enable X509 client authentication support
<x509 />
-->
<!-- Uncomment to limit the number of sessions a user can have -->
<session-management invalid-session-url="/timeout.jsp">
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>
</http>
<authentication-manager>
<authentication-provider>
<password-encoder hash="md5"/>
<jdbc-user-service data-source-ref="mysqlds"/>
</authentication-provider>
</authentication-manager>
</pre>
<br />
<pre class="Cpp" name="code"><intercept-url pattern="/user_authenticated.jsp" access="isAuthenticated()" />
</pre>
<br />
This is the JSP (user_authenticated.jsp) that we want to forward the user after getting authenticated, that will tell by this: access="isAuthenticated().<br />
<br />
<pre class="Cpp" name="code"><intercept-url pattern="/supervisor.jsp" access="hasRole('ROLE_SUPERVISOR')" />
</pre>
<br />
This will tell the Spring security module to authorize this JSP page access only to the users who are having ROLE_SUPERVISOR role.<br />
<br />
<br />
Within the <authentication-manager> tag you will enter all the details for authenticating a particular user. <br />
<br />
Passwords will be encoded with md5 algorithm. (<password-encoder hash="md5"/>).<br />
<br />
This will point the datasource to the DB where the user credentials are stored: <br />
<br />
<b><jdbc-user-service data-source-ref="mysqlds"/></b><br />
<br />
<b>mysqlds</b> is the datasource name.<br />
<br />
<u><b>applicationContext-db.xml</b></u><br />
<br />
This Spring configuration file is to configure the datasource lookup. (here im assuming that your JBoss installed on your local machine)<br />
<br />
<pre class="Cpp" name="code"><?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<bean id="mysqlds" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/mysqlds</value>
</property>
<property name="jndiEnvironment">
<props>
<prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
<prop key="java.naming.provider.url">jnp://localhost:1099</prop>
</props>
</property>
</bean>
</beans>
</pre>
<br />
Since you are going to deploy the application JBoss application server, you need to create another jboss-web.xml file with datasource information.<br />
<br />
<u><b>jboss-web.xml</b></u><br />
<br />
<pre class="Cpp" name="code"><?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<resource-ref>
<res-ref-name>jdbc/mysqlds</res-ref-name>
<jndi-name>java:/mysqlds</jndi-name>
</resource-ref>
</jboss-web>
</pre>
<br />
Finally you need to wire all the things with web.xml<br />
<br />
<u><b>web.xml</b></u><br />
<br />
<pre class="Cpp" name="code"><context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext-security.xml
/WEB-INF/applicationContext-db.xml
</param-value>
</context-param>
</pre>
<br />
Here we need to specify where are our Spring security configuration file and the datasource configuration file.<br />
<br />
<pre class="Cpp" name="code"><listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class> org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</pre>
<br />
Finally with the datasource information,<br />
<br />
<pre class="Cpp" name="code"><resource-ref>
<res-ref-name>jdbc/mysqlds</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</pre>
<br />
<br />
Spring assumes that your database contains particular tables in default. so you need to create those tables in order to follow the default way of Spring.<br />
<br />
Create those tables from below script.<br />
<pre class="Cpp" name="code">create table users(
username varchar(50) not null primary key,
password varchar(50) not null,
enabled boolean not null);
create table authorities (
username varchar(50) not null,
authority varchar(50) not null,
constraint fk_authorities_users foreign key(username) references users(username));
create unique index ix_auth_username on authorities (username,authority);
</pre>
<br />
Now you need to create the datasource file in JBoss and configure it.<br />
<br />
Go to JBOSS_HOME\server\default\deploy. Get a copy of the existing hsqldb-ds.xml file and name it as mysqldb-ds.xml and modify its contents as below.<br />
<br />
<b>mysqldb-ds.xml</b><br />
<br />
<pre class="Cpp" name="code"><datasources>
<local-tx-datasource>
<jndi-name>mysqlds</jndi-name>
<connection-url>jdbc:mysql://localhost:3306/test</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name>root</user-name>
<password>root</password>
<min-pool-size>5</min-pool-size>
<max-pool-size>20</max-pool-size>
<idle-timeout-minutes>0</idle-timeout-minutes>
</local-tx-datasource>
</datasources>
</pre>
<br />
save the file to the deploy folder of the JBoss and restart the server. (dont forget to put some values in the tables, since we are encoding passwords with md5 you need to put the encrypted passwords in the table.<br />
<br />
Use this site to do that. <br />
<br />
<a href="http://md5.gromweb.com/">http://md5.gromweb.com/</a><br />
<br />
You are done now.<br />
<br />
Right click on the eclipse project and export it as a WAR file and copy it to the JBoss deploy folder, and access the URL http://localhost:8080/test/user_authenticated.jsp (i have used test as the WAR file name)<br />
<br />
Now your eclipse project structure should look like this,<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://lh3.googleusercontent.com/-3QXjMvOD12Q/TX8Ud_k8iGI/AAAAAAAAAsw/4MGyWcsU3Pk/s1600/spring.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://lh3.googleusercontent.com/-3QXjMvOD12Q/TX8Ud_k8iGI/AAAAAAAAAsw/4MGyWcsU3Pk/s1600/spring.PNG" /></a></div>Kushan Jayathilakehttp://www.blogger.com/profile/14972462055058843725noreply@blogger.com13tag:blogger.com,1999:blog-7355044240007364151.post-54836221530257871662011-03-01T10:50:00.040+05:302011-03-15T16:14:05.356+05:30Hello World with Java Architecture for XML Binding - JAXB<u>What is JAXB?</u><br />
<br />
JAXB (Java Architecture for XML Binding) facilitates you to read or write to a XML file. since XML involves with Java everywhere, It will be very useful when working with Java. Here I'm assuming you are having some knowledge on XML.<br />
<br />
<u>What you should have</u><br />
<br />
1. <a href="http://jaxb.java.net/2.2.2/" mce_href="http://jaxb.java.net/2.2.2/">JAXB </a><br />
<br />
Download it and add its <b>bin</b> folder to your classpath.<br />
<br />
I have used eclipse as the IDE.<br />
<br />
Let's start...<br />
<br />
1. Create a project in eclipse called JAXB.<br />
2. Create the library directory and copy all the JAXB jars there. (lets call its "<b>lib</b>")<br />
3. Add <b>lib </b>to the build path.<br />
4. You should have a XML schema definition file, so let's create one. Let's name it as <b>GSCProfile.xsd</b><br />
5. Copy following content to the schema file.<br />
<br />
<b><u>GSCProfile.xsd</u></b><br />
<b><u><br />
</u></b><br />
<pre class="Cpp" name="code"><schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/GSCProfile"
xmlns:tns="http://www.example.org/GSCProfile" elementFormDefault="qualified">
<complexType name="GSC">
<sequence>
<element name="Name" type="string"></element>
<element name="Rating" type="int"></element>
</sequence>
</complexType>
<complexType name="Profile">
<sequence>
<element name="ProfileName" type="string"></element>
<element name="GSCElements" type="tns:GSC" maxOccurs="14" minOccurs="14">
</element>
</sequence>
</complexType>
<complexType name="GSCProfiles">
<sequence>
<element name="Profile" type="tns:Profile" maxOccurs="unbounded" minOccurs="1">
</element>
</sequence>
</complexType>
</schema>
</pre>There are 3 complex types called,<br />
<pre class="Cpp" name="code"><span style="font-family: 'inherit','serif';">1.GSCProfiles</span>
<span style="font-family: 'inherit','serif';">2.Profile</span>
<span style="font-family: 'inherit','serif';">3.GSC</span>
</pre><span style="font-family: 'inherit','serif';">GSCProfiles is the root of all. here how is the relationship goes, </span><br />
<br />
<span style="font-family: 'inherit','serif';">GSCProfiles ---< Profile ---< GSC</span><br />
<br />
<span style="font-family: 'inherit','serif';">Once you have added the <b>bin </b>folder to the classpath, go to the <b>src</b> folder of your project from command line and issue the following command,</span><br />
<b><span style="font-family: 'inherit','serif';"><br />
xjc -d binding -p com.jaxb.gsc GSCProfiles.xsd</span></b><br />
<br />
<span style="font-family: 'inherit','serif';">This will generates several classes in the above mentioned package (<b>com.jaxb.gsc</b>) one class for each complex type and an object factory and a package info class. </span><br />
<br />
<span style="font-family: 'inherit','serif';">create another class called <b>JAXBTest</b> in a diffrernt package, lets name that as <b>com.jaxb.test</b> </span><br />
<br />
<b><u><span style="font-family: 'inherit','serif';">JAXBTest.java</span></u></b><br />
<br />
Create this variable at class level. and variable to hold the xml file name.<br />
<pre class="Cpp" name="code">private static Map<String, Map<String, String>> gscProfileMap = new HashMap<String, Map<String, String>>();
/**
* Output xml file name.
*/
private static File xmlFile = new File("xml/GSCProfile.xml");
</pre> <br />
<span style="font-family: 'inherit','serif';">1. create a method called <b>saveGSCProfiles</b> and add following code fragments there. this method will save the content for it.</span><br />
<pre class="Cpp" name="code">public static void saveGSCProfiles() {
try {
Map<String, String> gscValueMap = new HashMap<String, String>();
// Adding GSC Elements
gscValueMap.put("Data Communications", "0");
gscValueMap.put("Distributed Data Processing", "0");
gscValueMap.put("Performance", "0");
gscValueMap.put("Heavily Used Configuration", "0");
gscValueMap.put("Transaction Rate", "0");
gscValueMap.put("Online Data Entry", "0");
gscValueMap.put("End User Efficiency", "0");
gscValueMap.put("Online Update", "0");
gscValueMap.put("Complex Processing", "0");
gscValueMap.put("Reusability", "0");
gscValueMap.put("Installation Ease", "0");
gscValueMap.put("Operational Ease", "0");
gscValueMap.put("Multiple Sites", "0");
gscValueMap.put("Facilitate Change", "0");
gscProfileMap.put("ProfileName", gscValueMap);
Set<String> pofileNames = gscProfileMap.keySet();
ObjectFactory factory = new ObjectFactory();
GSCProfiles gscProfiles = factory.createGSCProfiles();
for (String profileKey : pofileNames) {
Profile profile = factory.createProfile();
// Setting profile name.
profile.setProfileName(profileKey);
gscValueMap = gscProfileMap.get(profileKey);
Set<String> gscSet = gscValueMap.keySet();
for (String gscKey : gscSet) {
GSC gsc = factory.createGSC();
gsc.setName(gscKey);
gsc.setRating(Integer.parseInt(gscValueMap.get(gscKey)));
profile.getGSCElements().add(gsc);
}
gscProfiles.getProfile().add(profile);
}
JAXBContext jaxbContext = JAXBContext.newInstance("com.jaxb.gsc");
// Creating marshaller.
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
FileOutputStream outputStream = new FileOutputStream(xmlFile);
// Marshalling object in to the XML file.
marshaller.marshal(gscProfiles, outputStream);
} catch (JAXBException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
</pre> <br />
<br />
<span style="font-family: 'inherit','serif';"> 2. Create another method to read from the XML file. let's name this as <b>loadGSCProfiles</b></span><br />
<br />
<pre class="Cpp" name="code">public static void loadGSCProfiles() {
try {
JAXBContext jaxbContext = JAXBContext.newInstance("com.jaxb.gsc");
// Create unmarshaller.
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
GSCProfiles gscProfiles = (GSCProfiles) unmarshaller.unmarshal(xmlFile);
// Retrieving list of profiles.
List<Profile> profile = gscProfiles.getProfile();
for (Profile profile2 : profile) {
Map<String, String> gscValueMap = new HashMap<String, String>();
List<GSC> gsc = profile2.getGSCElements();
for (GSC gsc2 : gsc) {
gscValueMap.put(gsc2.getName(), gsc2.getRating() + "");
}
gscProfileMap.put(profile2.getProfileName(), gscValueMap);
}
} catch (JAXBException e) {
e.printStackTrace();
}
</pre><div class="MsoNormal"><br />
</div><div class="MsoNormal">Create a directory inside your eclipse project and name it as <b>xml</b>, and create a xml file called <b>GSCProfile.xml</b></div><div class="MsoNormal"><br />
</div><div class="MsoNormal">Write the main method in JAXBTest class and execute,</div><div class="MsoNormal"><br />
</div><div class="MsoNormal"><span style="font-size: small;"> <br />
<pre class="Cpp" name="code"> public static void main(String[] args) {
loadGSCProfiles();
saveGSCProfiles();
}
</pre></span></div><div class="MsoNormal" style="font-family: inherit;"><span style="font-size: small;"><br />
</span></div><div class="MsoNormal" style="font-family: inherit;"><span style="font-size: small;">Open your <b>GSCProfile.xml</b> file and see... :) </span></div><div class="MsoNormal"><br />
</div><div class="MsoNormal">Finally your eclipse project directory structure should like this,</div><div class="MsoNormal"><br />
</div><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="https://lh3.googleusercontent.com/-zXTWw-VJ8ts/TWyDmdt94WI/AAAAAAAAAr8/DdkG38dtDuc/s1600/jaxb.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://lh3.googleusercontent.com/-zXTWw-VJ8ts/TWyDmdt94WI/AAAAAAAAAr8/DdkG38dtDuc/s1600/jaxb.PNG" /></a></div></div><div class="MsoNormal"><br />
</div>Kushan Jayathilakehttp://www.blogger.com/profile/14972462055058843725noreply@blogger.com2tag:blogger.com,1999:blog-7355044240007364151.post-69218535694416976672011-02-22T14:55:00.023+05:302011-03-15T16:14:05.364+05:30Hello World with Apache Commons DigesterThis example will shows how to get started with Apache Commons Digester.<br />
<br />
<u>What is Apache Commons Digester? </u><br />
<br />
Simply, you can use this to read a XML file against a particular pattern (say, particular tag in XML file) and if it found, you can trigger some actions (say, a method, so that method will be called if that pattern is matched)<br />
<br />
So Let's start then,<br />
<br />
You shoud have JDK 1.5 installed and need to download several libraries, which are,<br />
<br />
1. <a href="http://download.filehat.com/apache//commons/digester/binaries/commons-digester-2.1-bin.zip">Apache Commons Digester Library.</a><br />
2. <a href="http://apache.cs.utah.edu//commons/logging/binaries/commons-logging-1.1.1-bin.zip">Apache Commons Logging.</a><br />
3. <a href="http://apache.inetbridge.net//commons/beanutils/binaries/commons-beanutils-1.8.3-bin.zip">Apache Commons BeanUtils.</a><br />
<br />
I'm using eclipse as the IDE, so here we go,<br />
<br />
Create a Java project from eclipse and add those downloaded libraries to that and set the build path correctly. <br />
<br />
Create a XML file with following contents,<br />
<br />
<br />
<pre class="Cpp" name="code"><?xml version="1.0" encoding="UTF-8"?>
<vehicles>
<suv>
<vendor>honda</vendor>
<model>HR-V</model>
<enginecapacity>1590CC</enginecapacity>
<enginetype>vtec</enginetype>
<doors>5</doors>
<color>silver</color>
</suv>
<suv>
<vendor>toyota</vendor>
<model>Prado</model>
<enginecapacity>3000CC</enginecapacity>
<enginetype>vvt-i</enginetype>
<doors>5</doors>
<color>silver</color>
</suv>
</vehicles>
</pre><br />
Create a Java class with a main method, Let's call this as <b>DigesterTest.java</b><br />
<br />
<span style="font-family: inherit;">add following method there,<br />
<span style="font-family: "Courier New",Courier,monospace;"> <br />
<pre class="Cpp" name="code">/**
* Action method. This will be called if there any matched content.
*
* @param vendor
* Value of the tag "vendor".
* @param model
* Value of the tag "model".
* @param enginecapacity
* Value of the tag "enginecapacity".
* @param enginetype
* Value of the tag "enginetype".
* @param doors
* Value of the tag "doors".
* @param color
* Value of the tag "color".
*/
public void getVehicleInfo(String vendor, String model,
String enginecapacity, String enginetype, String doors,
String color) {
System.out.println("Vendor : " + vendor);
System.out.println("Model : " + model);
System.out.println("Engine Capacity : " + enginecapacity);
System.out.println("Engine Type : " + enginetype);
System.out.println("Doors: " + doors);
System.out.println("Color : " + color);
}
</pre></span></span><br />
<span style="font-family: inherit;"><span style="font-family: "Courier New",Courier,monospace;"></span></span><br />
<span style="font-family: inherit;"><span style="font-family: "Courier New",Courier,monospace;"><br />
<br />
<pre class="Cpp" name="code">/**
* Creates certain patterns to check against with XML file, if there a
* match, action method will be called.
*
* @throws SAXException
* @throws IOException
*/
public void run() throws IOException, SAXException {
Digester digester = new Digester();
digester.push(new DigesterTest());
digester.addCallMethod("vehicles/suv", "getVehicleInfo", 6);
digester.addCallParam("vehicles/suv/vendor", 0);
digester.addCallParam("vehicles/suv/model", 1);
digester.addCallParam("vehicles/suv/enginecapacity", 2);
digester.addCallParam("vehicles/suv/enginetype", 3);
digester.addCallParam("vehicles/suv/doors", 4);
digester.addCallParam("vehicles/suv/color", 5);
InputStream inputStream = DigesterTest.class.getClassLoader()
.getResourceAsStream("vehicles.xml");
digester.parse(inputStream);
}
/**
* Main method.
*
* @param args
* @throws IOException
* @throws SAXException
*/
public static void main(String[] args) throws IOException, SAXException {
DigesterTest digesterTest = new DigesterTest();
digesterTest.run();
}
</pre></span></span><br />
<br />
Here is the directory structure of my eclipse project,<br />
<br />
<div style="text-align: left;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://lh6.googleusercontent.com/-hqqGTdt1NxM/TWOADmOgMeI/AAAAAAAAAr0/VqIKa8IHSqk/s1600/digester.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://lh6.googleusercontent.com/-hqqGTdt1NxM/TWOADmOgMeI/AAAAAAAAAr0/VqIKa8IHSqk/s1600/digester.PNG" /></a></div><div class="separator" style="clear: both; text-align: center;"></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-hqqGTdt1NxM/TWOADmOgMeI/AAAAAAAAAr0/VqIKa8IHSqk/s1600/digester.PNG" imageanchor="1"><br />
</a></div>Right click on <b>DigesterTest.java</b> and point to Run as > Java Application.Kushan Jayathilakehttp://www.blogger.com/profile/14972462055058843725noreply@blogger.com4tag:blogger.com,1999:blog-7355044240007364151.post-73790572510011389342010-12-08T10:54:00.196+05:302011-03-15T16:13:38.727+05:30Securing Web Services using Apache Rampart - Transport Level Security<style>
<!--
/* Font Definitions */
@font-face
{font-family:Courier;
panose-1:2 7 4 9 2 2 5 2 4 4;
mso-font-alt:"Courier New";
mso-font-charset:0;
mso-generic-font-family:modern;
mso-font-format:other;
mso-font-pitch:fixed;
mso-font-signature:3 0 0 0 1 0;}
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;
mso-font-charset:0;
mso-generic-font-family:roman;
mso-font-pitch:variable;
mso-font-signature:-1610611985 1107304683 0 0 159 0;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;
mso-font-charset:0;
mso-generic-font-family:swiss;
mso-font-pitch:variable;
mso-font-signature:-1610611985 1073750139 0 0 159 0;}
@font-face
{font-family:inherit;
panose-1:0 0 0 0 0 0 0 0 0 0;
mso-font-alt:"Times New Roman";
mso-font-charset:0;
mso-generic-font-family:roman;
mso-font-format:other;
mso-font-pitch:auto;
mso-font-signature:0 0 0 0 0 0;}
@font-face
{font-family:"Courier New \,Courier\,monospace\;";
panose-1:0 0 0 0 0 0 0 0 0 0;
mso-font-alt:"Times New Roman";
mso-font-charset:0;
mso-generic-font-family:roman;
mso-font-format:other;
mso-font-pitch:auto;
mso-font-signature:0 0 0 0 0 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-unhide:no;
mso-style-qformat:yes;
mso-style-parent:"";
margin-top:0in;
margin-right:0in;
margin-bottom:10.0pt;
margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:Calibri;
mso-fareast-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}
a:link, span.MsoHyperlink
{mso-style-noshow:yes;
mso-style-priority:99;
color:blue;
text-decoration:underline;
text-underline:single;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-noshow:yes;
mso-style-priority:99;
color:purple;
mso-themecolor:followedhyperlink;
text-decoration:underline;
text-underline:single;}
p
{mso-style-priority:99;
mso-margin-top-alt:auto;
margin-right:0in;
mso-margin-bottom-alt:auto;
margin-left:0in;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:"Times New Roman","serif";
mso-fareast-font-family:"Times New Roman";}
.MsoChpDefault
{mso-style-type:export-only;
mso-default-props:yes;
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:Calibri;
mso-fareast-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}
.MsoPapDefault
{mso-style-type:export-only;
margin-bottom:10.0pt;
line-height:115%;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;
mso-header-margin:.5in;
mso-footer-margin:.5in;
mso-paper-source:0;}
div.WordSection1
{page:WordSection1;}
-->
</style> Note that you will find many articles about this topic, but I'm going to show you how to do this in <b>WebSphere Application Server 6.1.0.27.</b><br />
<br />
<b><u>Apache Rampart</u></b><br />
Apache Rampart acts as the security module for Axis2. You can use Rampart for securing web services by enforcing authentication, integrity and confidentiality.<br />
You can download it from <b><a href="http://axis.apache.org/axis2/java/rampart/download/1.5/download.cgi">here</a></b>.<br />
Download it and copy it's <b>JAR </b>file to the <b>WEB-INF/libs</b> directory of your web application and copy the <b>modules</b> directory in the Rampart distribution to <b>WEB-INF </b>directory of you web application.<br />
We will create a simple Web Service and secure it using Apache Rampart. Let's write the service implemetation class.<br />
<b><u>service class</u></b><br />
<pre class="Cpp" name="code">package com.test;
public class Calculator {
public int addService(final int a, final int b) {
return a + b;
}
}
</pre>Now, Let's write the <b>services.xml</b>, which tells Axis what is your service class and what are the methods you are going to expose through the web service.<br />
<br />
<b><u>services.xml</u></b><br />
<pre class="Cpp" name="code"><service>
<parameter locked="false" name="ServiceClass">
com.test.Calculator</parameter>
<operation name="addService">
<messagereceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver">
</messagereceiver>
</operation>
</service>
</pre><br />
<b><u><span style="font-family: "inherit","serif";">Password callback class</span></u></b><span style="font-family: "inherit","serif";"> <o:p></o:p></span><br />
<br />
<span style="font-family: "inherit","serif";">Since we are going to use password callback class to verify the client provided username and the password, we should implement a password callback class.<o:p></o:p></span><br />
<br />
<pre class="Cpp" name="code">package com.test;
import org.apache.ws.security.WSPasswordCallback;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import java.io.IOException;
public class PWCBHandler implements CallbackHandler {
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
//When the server side need to authenticate the user
WSPasswordCallback pwcb = (WSPasswordCallback)callbacks[i];
// For plain text password scenarios
if (pwcb.getUsage() == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN) {
if (pwcb.getIdentifier().equals("kushanxp")
&& pwcb.getPassword().equals("kushan"))
{
//If authentication successful, simply return
return;
} else {
throw new UnsupportedCallbackException(callbacks[i], "check failed");
}
// For digested password scenarios
} else if (pwcb.getUsage() == WSPasswordCallback.USERNAME_TOKEN ) {
if (pwcb.getIdentifier().equals("kushanxp"))
{
//We simply set the password, Username Token processor verifies the digest
pwcb.setPassword("kushan");
return;
}
}
}
}
}
</pre><span style="font-family: "inherit","serif";">Now we have to add policy based information to the <b>services.xml,</b></span><br />
<b><u><span style="font-family: "inherit","serif";">services.xml</span></u></b><br />
<br />
<br />
<pre class="Cpp" name="code"><service>
<module ref="rampart">
<parameter locked="false" name="ServiceClass">com.ws.service.Calculator
</parameter>
<operation name="addService">
<messagereceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver">
</messagereceiver>
<wsp:policy wsu:id="UTOverTransport" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsp:exactlyone>
<wsp:all>
<sp:transportbinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:policy>
<sp:transporttoken>
<wsp:policy>
<sp:httpstoken requireclientcertificate="false">
</sp:httpstoken>
</wsp:policy>
<sp:algorithmsuite>
<wsp:policy>
<sp:basic256>
</sp:basic256>
</wsp:policy>
<sp:layout>
<wsp:policy>
<sp:lax>
</sp:lax>
</wsp:policy>
<sp:includetimestamp>
</sp:includetimestamp>
</sp:layout>
<sp:signedsupportingtokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:policy>
<sp:usernametoken sp:includetoken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
</sp:usernametoken>
</wsp:policy>
<ramp:rampartconfig xmlns:ramp="http://ws.apache.org/rampart/policy">
<ramp:passwordcallbackclass> com.test.PWCBHandler
</ramp:passwordcallbackclass>
</ramp:rampartconfig>
</sp:signedsupportingtokens>
</sp:algorithmsuite>
</sp:transporttoken>
</wsp:policy>
</sp:transportbinding>
</wsp:all>
</wsp:exactlyone>
</wsp:policy>
</operation>
</module>
</service>
</pre><br />
<span style="font-family: "inherit","serif";">Note that you can find the policy based configurations from</span><span style="font-family: Courier; font-size: 10pt;"> </span> <span style="font-family: Courier; font-size: 10pt;"> </span><b><span style="font-family: Courier;"><wsp:Policy></span></b><span style="font-family: Courier; font-size: 10pt;"> to </span><b><span style="font-family: "Courier New";"></wsp:Policy></span></b><b><span style="font-family: "Courier New"; font-size: 10pt;"> </span></b><span style="font-family: "inherit","serif";">and you have to mention your password callback class in the </span><span style="font-family: "inherit","serif"; font-size: 10pt;"> </span> <b><span style="font-family: Courier;"><ramp:passwordCallbackClass></span></b> <b><span style="font-family: "Courier New";"> com.test.PWCBHandler</span></b><span style="font-family: "Courier New";"><o:p></o:p></span> <b><span style="font-family: Courier;"></ramp:passwordCallbackClass></span></b> <b><u><span style="font-family: "inherit","serif";">Engaging Rampart </span></u></b> <span style="font-family: "inherit","serif";">You may notice that I have added</span><span style="font-family: Courier;"> </span><b><span style="font-family: "Courier New";"><module ref="rampart"/> </span></b><span style="font-family: "inherit","serif";">in top of the services.xml file, This will tell Axis2 that we going to engage Rampart with our web service. Note that this is local to this service, if you want to engage Rampart globally to all of your services, then you have to add</span><span style="font-family: "Arial","sans-serif";"> </span><b><span style="font-family: Courier;"><module ref="rampart"/> </span></b><span style="font-family: Courier;">this line to </span><b><span style="font-family: "Courier New";">axis2.xml</span></b><span style="font-family: Courier;"> file.</span> Now you are almost complete, Let's create a <b>WAR </b>file with our service and deploy in on <b>WebSphere Application Server. </b> <span style="font-family: "inherit","serif";">Your WAR file directory structure should be as follows,</span> (Assume your WAR file name is <b>calculator.war</b>) <b><span style="font-family: Courier;">calculator.war </span></b> <span style="font-family: "inherit","serif";">Now we have done all the coding for the service level, now it's time to move to client end.</span> <b><u><span style="font-family: Courier;">Client Implementation</span></u></b> <b><span style="font-family: Courier;"> </span></b><br />
<br />
<u><b><span style="font-family: Courier;">client.java</span></b></u><br />
<b><span style="font-family: Courier;"> </span></b> <br />
<br />
<pre class="Cpp" name="code">package com.ws.client;
import java.io.FileNotFoundException;
import java.rmi.RemoteException;
import javax.xml.stream.XMLStreamException;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axis2.AxisFault;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.neethi.Policy;
import org.apache.neethi.PolicyEngine;
import org.apache.rampart.RampartMessageData;
public class Client {
/** * @param args */
public static void main(String[] args) {
try {
System.setProperty("javax.net.ssl.trustStore", "keys/service.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "kushan");
ConfigurationContext ctx = ConfigurationContextFactory
.createConfigurationContextFromFileSystem("repo", null);
CalculatorStub stub = new CalculatorStub(ctx,
"https://localhost:8443/axis2/services/Calculator");
ServiceClient client = stub._getServiceClient();
client.engageModule("rampart");
Options options = client.getOptions();
options.setUserName("kushanxp");
options.setPassword("kushan");
options.setProperty(RampartMessageData.KEY_RAMPART_POLICY,
loadPolicy("resources/policy.xml"));
int a = 3;
int b = 4;
int result = stub.add(a, b);
System.out.println(a + " + " + b + " = " + result);
} catch (AxisFault e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
/**
*
* Loads the policy.
*
*
*
* @param xmlPath
*
* @return
*/
private static Policy loadPolicy(String xmlPath) {
StAXOMBuilder builder = null;
try {
builder = new StAXOMBuilder(xmlPath);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (XMLStreamException e) {
e.printStackTrace();
}
return PolicyEngine.getPolicy(builder.getDocumentElement());
}
}
</pre>Kushan Jayathilakehttp://www.blogger.com/profile/14972462055058843725noreply@blogger.com2tag:blogger.com,1999:blog-7355044240007364151.post-72705160954940048312010-12-07T16:37:00.028+05:302011-03-15T16:14:05.368+05:30Embedding Axis2 into an Existing ApplicationMany of you may came up with implementing Web Services for existing application, here I have done it using Apache Axis 2, So here what you need to do,<br />
<br />
You should edit your <b>web.xml</b> file found in <b>WEB-INF</b> directory, and there you have to configure Axis specific information, (You must configure AxisServlet there, so when the application deploying server will identify that Axis2 is plugged in to this application)<br />
<br />
<u>web.xml</u><br />
<br />
<pre class="Cpp" name="code"> <servlet>
<display-name>Apache-Axis Servlet</display-name>
<servlet-name>AxisServlet</servlet-name>
<servlet-class>
org.apache.axis2.transport.http.AxisServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
</pre><br />
Now add servlet mapping,<br />
<pre class="Cpp" name="code"> <servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</pre><br />
This will tell the Axis Servlet that all your Web Services will include in a directory called <b>services</b>, So the service URL's must have <b>services</b> text within their URL's<br />
<br />
If you do not wish to add your web services in a directory called services, you can change this to something else,<br />
<br />
i.e :<br />
<span style="font-family: "Courier New",Courier,monospace;"> <servlet-mapping></span><br />
<span style="font-family: "Courier New",Courier,monospace;"> <servlet-name>AxisServlet</servlet-name></span><br />
<span style="font-family: "Courier New",Courier,monospace;"> <url-pattern>/serviceapps/*</url-pattern></span><br />
<span style="font-family: "Courier New",Courier,monospace;"> </servlet-mapping></span><br />
<br />
<br />
And you need to tell <b>axis2.xml</b> that where are your services,<br />
<br />
<u>axis2.xml</u><br />
<pre class="Cpp" name="code"><parameter name="servicePath">serviceapps</parameter>
</pre><u>note</u><br />
<br />
Axis2 assumes that all your service implementations are in a directory called <b>services</b>, in <b>WEB-INF</b> folder. so if you are not changing that, you don't have to modify <b>axis2.xml</b> file.<br />
<br />
Thats all you have to do, Remember to copy all the <b>JAR </b>files in Axis2 distribution to your <b>WEB-INF/lib</b> directory :)<br />
<br />
So when the application deploying in the server, it will initialize the AxisServlet and loads the web service implementations from default locations,<br />
<br />
<u>Default Service Location</u><br />
<u> </u><br />
WEB-INF/services<br />
<br />
<u>Default Module Location</u><br />
<br />
WEB-INF/modules<br />
<br />
<u>Default Axis2 XML Location</u><br />
<br />
WEB-INF/conf<br />
<br />
<u>Directory structure.</u> <br />
<br />
<div class="separator" style="clear: both; text-align: center;"></div>Kushan Jayathilakehttp://www.blogger.com/profile/14972462055058843725noreply@blogger.com3