I think this would be good example for applying the security for the simple rest endpoint. Lets think we already have some rest endpoint without security but we need to expose this with the OAuth2.0 base security.
you can achieve this task with the following steps.
1. Create the custom handler to validate the Bearer token.
2. Create API element in the ESB and pointing the rest endpoint that you have
3. Include created handler to the created API element.
4. Go to IS and create the OAuth2.0 application and get the Access token form IS
5. Invoke the API with the valid access token.
Functional Scenario
1. Creating custom handler (Download the mvn project here)
You need to extends AbstractHandler and implements ManagedLifecycle as follows. as well I'm getting some parameters from the axis2.xml
[sourcecode language="java"]
package org.wso2.handler;
/**
* Created with IntelliJ IDEA.
* User: dinuka
* Date: 4/4/13
* Time: 3:46 PM
* To change this template use File | Settings | File Templates.
*/
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.axis2.transport.http.HTTPConstants;
import org.apache.axis2.transport.http.HttpTransportProperties;
import org.apache.http.HttpHeaders;
import org.apache.synapse.core.axis2.Axis2MessageContext;
import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO;
import org.apache.synapse.ManagedLifecycle;
import org.apache.synapse.MessageContext;
import org.apache.synapse.core.SynapseEnvironment;
import org.apache.synapse.rest.AbstractHandler;
import java.util.Map;
public class SimpleOauthHandler extends AbstractHandler implements ManagedLifecycle {
private String securityHeader = HttpHeaders.AUTHORIZATION;
private String consumerKeyHeaderSegment = "Bearer";
private String oauthHeaderSplitter = ",";
private String consumerKeySegmentDelimiter = " ";
private String oauth2TokenValidationService = "oauth2TokenValidationService";
private String identityServerUserName = "identityServerUserName";
private String identityServerPw = "identityServerPw";
@Override
public boolean handleRequest(MessageContext messageContext) {
try{
ConfigurationContext configCtx = ConfigurationContextFactory.createConfigurationContextFromFileSystem(null, null);
//Read parameters from axis2.xml
String identityServerUrl = messageContext.getConfiguration().getAxisConfiguration().getParameter(oauth2TokenValidationService).getValue().toString();
String username = messageContext.getConfiguration().getAxisConfiguration().getParameter(identityServerUserName).getValue().toString();
String password = messageContext.getConfiguration().getAxisConfiguration().getParameter(identityServerPw).getValue().toString();
OAuth2TokenValidationServiceStub stub = new OAuth2TokenValidationServiceStub(configCtx,identityServerUrl);
ServiceClient client = stub._getServiceClient();
Options options = client.getOptions();
HttpTransportProperties.Authenticator authenticator = new HttpTransportProperties.Authenticator();
authenticator.setUsername(username);
authenticator.setPassword(password);
authenticator.setPreemptiveAuthentication(true);
options.setProperty(HTTPConstants.AUTHENTICATE, authenticator);
client.setOptions(options);
OAuth2TokenValidationRequestDTO dto = new OAuth2TokenValidationRequestDTO();
dto.setTokenType("bearer");
Map headers = (Map) ((Axis2MessageContext) messageContext).getAxis2MessageContext().
getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
String apiKey = null;
if (headers != null) {
apiKey = extractCustomerKeyFromAuthHeader(headers);
}
dto.setAccessToken(apiKey);
//validate passed apiKey(token)
if(stub.validate(dto).getValid()){
return true;
}else{
return false;
}
}catch(Exception e){
e.printStackTrace();
return false;
}
}
public String extractCustomerKeyFromAuthHeader(Map headersMap) {
//From 1.0.7 version of this component onwards remove the OAuth authorization header from
// the message is configurable. So we dont need to remove headers at this point.
String authHeader = (String) headersMap.get(securityHeader);
if (authHeader == null) {
return null;
}
if (authHeader.startsWith("OAuth ") || authHeader.startsWith("oauth ")) {
authHeader = authHeader.substring(authHeader.indexOf("o"));
}
String[] headers = authHeader.split(oauthHeaderSplitter);
if (headers != null) {
for (int i = 0; i < headers.length; i++) {
String[] elements = headers[i].split(consumerKeySegmentDelimiter);
if (elements != null && elements.length > 1) {
int j = 0;
boolean isConsumerKeyHeaderAvailable = false;
for (String element : elements) {
if (!"".equals(element.trim())) {
if (consumerKeyHeaderSegment.equals(elements[j].trim())) {
isConsumerKeyHeaderAvailable = true;
} else if (isConsumerKeyHeaderAvailable) {
return removeLeadingAndTrailing(elements[j].trim());
}
}
j++;
}
}
}
}
return null;
}
private String removeLeadingAndTrailing(String base) {
String result = base;
if (base.startsWith("\"") || base.endsWith("\"")) {
result = base.replace("\"", "");
}
return result.trim();
}
@Override
public boolean handleResponse(MessageContext messageContext) {
return true;
}
@Override
public void init(SynapseEnvironment synapseEnvironment) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void destroy() {
//To change body of implemented methods use File | Settings | File Templates.
}
}
[/sourcecode]
2. Now I take rest unsecured endpoint as "https://www.google.lk/search?q=wso2"(You can use your own endpoint)
Lets look at how to configure the WSO2 ESB with this endpoint.
Start the ESB 4.6.0 and Sign in as admin.
Then go to Source View.
Insert following xml configuration in to the source view to create the API element name as TestGoogle
[sourcecode language="xml"]
<api name="TestGoogle" context="/search">
<resource methods="GET">
<inSequence>
<log level="custom">
<property name="Test" value="Test"/>
</log>
<send>
<endpoint>
<address uri="https://www.google.lk/search?q=wso2"/>
</endpoint>
</send>
</inSequence>
</resource>
<handlers>
<handler class="org.wso2.handler.SimpleOauthHandler"/>
</handlers>
</api>
[/sourcecode]
3. We need to add the created custom handler.jar in to $ESB_HOME/repository/components/libs and go to the $ESB_HOME/repository/conf/axis2/axis2.xml and put the following parameters.
[sourcecode language="xml"]
<!-- OAuth2 Token Validation Service -->
<parameter name="oauth2TokenValidationService">https://localhost:9444/services/OAuth2TokenValidationService</parameter>
<!-- Server credentials -->
<parameter name="identityServerUserName">admin</parameter>
<parameter name="identityServerPw">admin</parameter>
[/sourcecode]
restart the ESB.
Again go to source view and place the following xml to engage the custom handler in to the API element
[sourcecode language="xml"]
<handlers>
<handler class="org.wso2.handler.SimpleOauthHandler"/>
</handlers>
[sourcecode]
Total configuration looks like this
[sourcecode language="xml"]
<api name="TestGoogle" context="/search">
<resource methods="GET">
<inSequence>
<log level="custom">
<property name="Test" value="Test"/>
</log>
<send>
<endpoint>
<address uri="https://www.google.lk/search?q=wso2"/>
</endpoint>
</send>
</inSequence>
</resource>
<handlers>
<handler class="org.wso2.handler.SimpleOauthHandler"/>
</handlers>
</api>
[/sourcecode]
4. Start the WSO2 Identity server and create the Oauth2.0 Application
Request the access token from IS you need to pass the ClientID and Client Secret with the curl request.
[sourcecode language="console"]
curl -v -X POST --user <strong>R2CNjiq672f6xXQabAfWbYby2nca</strong>:<strong>QhEQi9eJv8BmSinPBnWscCFFDgsa</strong> -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" -k -d "grant_type=password&username=admin&password=admin" https://localhost:9444/oauth2endpoints/token
[/sourcecode]
Then you will receive the access token
5. Now you can invoke the API with the received access token
curl -v -X GET -H "Authorization: Bearer ca1799fc84986bd87c120ba499838a7" http://10.100.1.198:8280/search
Friday, April 5, 2013
Thursday, April 4, 2013
Custom JDBC user store manager with Custom properties as Claims in WSO2IS 4.1.1 alpha
In my early blog post I have describe how to write the custom user store manager and plug in to the WSO2 Identity Server. Now I'm going to explain how we can plug the user properties as claims and how to do some authorization with that properties. First of all you need to read my early blog post (How to write Custom JDBC user store manager with WSO2IS 4.1.1 alpha)
I have modify the DB Schema as follows
[sourcecode language="sql"]
CREATE TABLE CUSTOMER_DATA (
CUSTOMER_ID INTEGER NOT NULL AUTO_INCREMENT,
CUSTOMER_NAME VARCHAR(255) NOT NULL,
PASSWORD VARCHAR(255) NOT NULL,
EMAIL VARCHAR(255) NOT NULL,
AGE VARCHAR(255) NOT NULL,
STATUS VARCHAR(255) NOT NULL,
PRIMARY KEY (CUSTOMER_ID),
UNIQUE(CUSTOMER_NAME)
);
INSERT INTO CUSTOMER_DATA (CUSTOMER_NAME, PASSWORD,EMAIL,AGE,STATUS) VALUES("dinuka" ,"dinuka","dinukam@wso2.com","25","ACTIVE");
INSERT INTO CUSTOMER_DATA (CUSTOMER_NAME, PASSWORD,EMAIL,AGE,STATUS) VALUES("malinda" ,"malinda","malinda@gmail.com","25","INACTIVE");
[/sourcecode]
As I mention in the early post we need to create the data sources in master-datasources.xml and plug the newly created JDBCUserStoreManager through the user-mgt.xml
1. Lets look at the modification of JDBCUserStoreManager.
If we need to get some user properties as claims then you need to override the following methods in JDBCUserStoreManager (Download the mvn project here).
[sourcecode language="java"]
@Override
protected String getProperty(Connection dbConnection, String userName, String propertyName,
String profileName) throws UserStoreException {
String sqlStmt = realmConfig.getUserStoreProperty(JDBCRealmConstants.GET_PROPS_FOR_PROFILE);
if (sqlStmt == null) {
throw new UserStoreException("The sql statement for add user property sql is null");
}
PreparedStatement prepStmt = null;
ResultSet rs = null;
String value = null;
try {
prepStmt = dbConnection.prepareStatement(sqlStmt);
prepStmt.setString(1, userName);
rs = prepStmt.executeQuery();
while (rs.next()) {
if(propertyName.equals("EMAIL")){
value = rs.getString(1);
}else if(propertyName.equals("AGE")){
value = rs.getString(2);
}else if(propertyName.equals("STATUS")){
value = rs.getString(3);
}
}
return value;
} catch (SQLException e) {
log.error("Using sql : " + sqlStmt);
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(null, rs, prepStmt);
}
}
@Override
public Map<String, String> getUserPropertyValues(String userName, String[] propertyNames,
String profileName) throws UserStoreException {
if (profileName == null) {
profileName = UserCoreConstants.DEFAULT_PROFILE;
}
Connection dbConnection = null;
String sqlStmt = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
String[] propertyNamesSorted = propertyNames.clone();
Arrays.sort(propertyNamesSorted);
Map<String, String> map = new HashMap<String, String>();
try {
dbConnection = getDBConnection();
sqlStmt = realmConfig.getUserStoreProperty(JDBCRealmConstants.GET_PROPS_FOR_PROFILE);
prepStmt = dbConnection.prepareStatement(sqlStmt);
prepStmt.setString(1, userName);
rs = prepStmt.executeQuery();
while (rs.next()) {
String email = rs.getString(1);
String age = rs.getString(2);
String status = rs.getString(3);
if (Arrays.binarySearch(propertyNamesSorted, "EMAIL") >= 0) {
map.put("EMAIL", email);
}
if(Arrays.binarySearch(propertyNamesSorted, "AGE") >= 0){
map.put("AGE", age);
}
if(Arrays.binarySearch(propertyNamesSorted, "STATUS") >= 0){
map.put("STATUS", status);
}
}
return map;
} catch (SQLException e) {
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection, rs, prepStmt);
}
}
[/sourcecode]
2. In this code you can see we are using some external sql query as GET_PROPS_FOR_PROFILE (realmConfig.getUserStoreProperty(JDBCRealmConstants.GET_PROPS_FOR_PROFILE);) so we need to pass it from user-mgt.xml as follows.
[sourcecode language="xml"]
<UserManager>
<Realm>
<Configuration>
<AddAdmin>true</AddAdmin>
<AdminRole>admin</AdminRole>
<AdminUser>
<UserName>admin</UserName>
<Password>admin</Password>
</AdminUser>
<EveryOneRoleName>everyone</EveryOneRoleName> <!-- By default users in this role sees the registry root -->
<Property name="dataSource">jdbc/WSO2CarbonDB</Property>
<Property name="MultiTenantRealmConfigBuilder">org.wso2.carbon.user.core.config.multitenancy.SimpleRealmConfigBuilder</Property>
<!-- Use the following MultiTenantRealmConfigBuilder with LDAP based UserStoreManagers-->
<!--Property name="MultiTenantRealmConfigBuilder">org.wso2.carbon.user.core.config.multitenancy.CommonLDAPRealmConfigBuilder</Property-->
</Configuration>
<UserStoreManager class="org.wso2.carbon.user.core.jdbc.JDBCUserStoreManager">
<Property name="ReadOnly">false</Property>
<Property name="dataSource">jdbc/WSO2CarbonDB</Property>
<Property name="MaxUserNameListLength">100</Property>
<Property name="Disabled">false</Property>
<Property name="IsEmailUserName">false</Property>
<Property name="DomainCalculation">default</Property>
<Property name="PasswordDigest">SHA-256</Property>
<Property name="StoreSaltedPassword">true</Property>
<Property name="ReadGroups">true</Property>
<Property name="WriteGroups">true</Property>
<Property name="UserNameUniqueAcrossTenants">false</Property>
<Property name="PasswordJavaRegEx">^[\S]{5,30}$</Property>
<Property name="PasswordJavaScriptRegEx">^[\S]{5,30}$</Property>
<Property name="UsernameJavaRegEx">^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$</Property>
<Property name="UsernameJavaScriptRegEx">^[\S]{3,30}$</Property>
<Property name="RolenameJavaRegEx">^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$</Property>
<Property name="RolenameJavaScriptRegEx">^[\S]{3,30}$</Property>
<Property name="UserRolesCacheEnabled">true</Property>
<Property name="MaxRoleNameListLength">100</Property>
<Property name="MaxUserNameListLength">100</Property>
</UserStoreManager>
<UserStoreManager class="org.wso2.carbon.jdbc.sample.SampleJDBCUserStoreManager">
<Property name="ReadOnly">false</Property>
<Property name="dataSource">jdbc/SampleUserStore</Property>
<Property name="MaxUserNameListLength">100</Property>
<Property name="Disabled">false</Property>
<Property name="IsEmailUserName">false</Property>
<Property name="DomainCalculation">default</Property>
<Property name="PasswordDigest">SHA-256</Property>
<Property name="StoreSaltedPassword">true</Property>
<Property name="ReadGroups">true</Property>
<Property name="WriteGroups">true</Property>
<Property name="UserNameUniqueAcrossTenants">false</Property>
<Property name="PasswordJavaRegEx">^[\S]{5,30}$</Property>
<Property name="PasswordJavaScriptRegEx">^[\S]{5,30}$</Property>
<Property name="UsernameJavaRegEx">^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$</Property>
<Property name="UsernameJavaScriptRegEx">^[\S]{3,30}$</Property>
<Property name="RolenameJavaRegEx">^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$</Property>
<Property name="RolenameJavaScriptRegEx">^[\S]{3,30}$</Property>
<Property name="UserRolesCacheEnabled">true</Property>
<Property name="MaxRoleNameListLength">100</Property>
<Property name="MaxUserNameListLength">100</Property>
<Property name="DomainName">sample.com</Property>
<Property name="SelectUserSQL">SELECT * FROM CUSTOMER_DATA WHERE CUSTOMER_NAME=?</Property>
<Property name="UserFilterSQL">SELECT CUSTOMER_NAME FROM CUSTOMER_DATA WHERE CUSTOMER_NAME LIKE ? ORDER BY CUSTOMER_ID</Property>
<Property name="GetUserPropertiesForProfileSQL">SELECT EMAIL,AGE,STATUS FROM CUSTOMER_DATA WHERE CUSTOMER_NAME=?</Property>
</UserStoreManager>
<AuthorizationManager
class="org.wso2.carbon.user.core.authorization.JDBCAuthorizationManager">
<Property name="AdminRoleManagementPermissions">/permission</Property>
<Property name="AuthorizationCacheEnabled">true</Property>
</AuthorizationManager>
</Realm>
</UserManager>
[/sourcecode]
3. Same as you did in early post you have to place the mysql-connector-java-5.1.7-bin.jar and Sample_user_store-1.0.jar in to $IS_HOME/repository/component/libs
4. Start the Identity server and Sign in as admin.
5. Go to claim management.
Now you can see some Available Claim Dialects here. In the user store manager is using the http://wso2.org/claims so we need to add the new claim mapping on this.
5. Go to http://wso2.org/claims Dialect.
6. Add new Claim EMAIL
Here you need to specify the Mapped Attribute (s) as EMAIL because in our custom user store manager check the property name as "EMAIL","AGE","STATUS"
7. Add new Claim AGE
8. Add new Claim STATUS
9. Lets look at the users
And go to User profile
Now you can see the properties in the database is coming under user profile.
10. Now we need to use those properties and do some authorization. So we can easily move to XACML engine coming with the Identity server to do the needful. Here I'm not going to explain the behavior of the XACML Engine in Identity server but you can follow my early blog posts such as
Authentication and Authorization with WSO2ESB and WSO2IS
XACML Authorization
11. Now I'm going to create the XACML policy buy using the claims that we newly added.
You can see the claim names that we mapped early so you can select those from the UI.
Click on the policy name and go to source view of XACML policy.
and replace the Deny with Permit and update the policy.
12. Now enable the created policy as follows.
13. Go to Tryit and test your policy.
This is very basic example but when its coming to the real world example you can do so many things with this user store extensible facility. as well you can do all the above stuff with the use of web services which are exposed by WSO2 Identity Server.
I have modify the DB Schema as follows
[sourcecode language="sql"]
CREATE TABLE CUSTOMER_DATA (
CUSTOMER_ID INTEGER NOT NULL AUTO_INCREMENT,
CUSTOMER_NAME VARCHAR(255) NOT NULL,
PASSWORD VARCHAR(255) NOT NULL,
EMAIL VARCHAR(255) NOT NULL,
AGE VARCHAR(255) NOT NULL,
STATUS VARCHAR(255) NOT NULL,
PRIMARY KEY (CUSTOMER_ID),
UNIQUE(CUSTOMER_NAME)
);
INSERT INTO CUSTOMER_DATA (CUSTOMER_NAME, PASSWORD,EMAIL,AGE,STATUS) VALUES("dinuka" ,"dinuka","dinukam@wso2.com","25","ACTIVE");
INSERT INTO CUSTOMER_DATA (CUSTOMER_NAME, PASSWORD,EMAIL,AGE,STATUS) VALUES("malinda" ,"malinda","malinda@gmail.com","25","INACTIVE");
[/sourcecode]
As I mention in the early post we need to create the data sources in master-datasources.xml and plug the newly created JDBCUserStoreManager through the user-mgt.xml
1. Lets look at the modification of JDBCUserStoreManager.
If we need to get some user properties as claims then you need to override the following methods in JDBCUserStoreManager (Download the mvn project here).
[sourcecode language="java"]
@Override
protected String getProperty(Connection dbConnection, String userName, String propertyName,
String profileName) throws UserStoreException {
String sqlStmt = realmConfig.getUserStoreProperty(JDBCRealmConstants.GET_PROPS_FOR_PROFILE);
if (sqlStmt == null) {
throw new UserStoreException("The sql statement for add user property sql is null");
}
PreparedStatement prepStmt = null;
ResultSet rs = null;
String value = null;
try {
prepStmt = dbConnection.prepareStatement(sqlStmt);
prepStmt.setString(1, userName);
rs = prepStmt.executeQuery();
while (rs.next()) {
if(propertyName.equals("EMAIL")){
value = rs.getString(1);
}else if(propertyName.equals("AGE")){
value = rs.getString(2);
}else if(propertyName.equals("STATUS")){
value = rs.getString(3);
}
}
return value;
} catch (SQLException e) {
log.error("Using sql : " + sqlStmt);
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(null, rs, prepStmt);
}
}
@Override
public Map<String, String> getUserPropertyValues(String userName, String[] propertyNames,
String profileName) throws UserStoreException {
if (profileName == null) {
profileName = UserCoreConstants.DEFAULT_PROFILE;
}
Connection dbConnection = null;
String sqlStmt = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
String[] propertyNamesSorted = propertyNames.clone();
Arrays.sort(propertyNamesSorted);
Map<String, String> map = new HashMap<String, String>();
try {
dbConnection = getDBConnection();
sqlStmt = realmConfig.getUserStoreProperty(JDBCRealmConstants.GET_PROPS_FOR_PROFILE);
prepStmt = dbConnection.prepareStatement(sqlStmt);
prepStmt.setString(1, userName);
rs = prepStmt.executeQuery();
while (rs.next()) {
String email = rs.getString(1);
String age = rs.getString(2);
String status = rs.getString(3);
if (Arrays.binarySearch(propertyNamesSorted, "EMAIL") >= 0) {
map.put("EMAIL", email);
}
if(Arrays.binarySearch(propertyNamesSorted, "AGE") >= 0){
map.put("AGE", age);
}
if(Arrays.binarySearch(propertyNamesSorted, "STATUS") >= 0){
map.put("STATUS", status);
}
}
return map;
} catch (SQLException e) {
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection, rs, prepStmt);
}
}
[/sourcecode]
2. In this code you can see we are using some external sql query as GET_PROPS_FOR_PROFILE (realmConfig.getUserStoreProperty(JDBCRealmConstants.GET_PROPS_FOR_PROFILE);) so we need to pass it from user-mgt.xml as follows.
[sourcecode language="xml"]
<UserManager>
<Realm>
<Configuration>
<AddAdmin>true</AddAdmin>
<AdminRole>admin</AdminRole>
<AdminUser>
<UserName>admin</UserName>
<Password>admin</Password>
</AdminUser>
<EveryOneRoleName>everyone</EveryOneRoleName> <!-- By default users in this role sees the registry root -->
<Property name="dataSource">jdbc/WSO2CarbonDB</Property>
<Property name="MultiTenantRealmConfigBuilder">org.wso2.carbon.user.core.config.multitenancy.SimpleRealmConfigBuilder</Property>
<!-- Use the following MultiTenantRealmConfigBuilder with LDAP based UserStoreManagers-->
<!--Property name="MultiTenantRealmConfigBuilder">org.wso2.carbon.user.core.config.multitenancy.CommonLDAPRealmConfigBuilder</Property-->
</Configuration>
<UserStoreManager class="org.wso2.carbon.user.core.jdbc.JDBCUserStoreManager">
<Property name="ReadOnly">false</Property>
<Property name="dataSource">jdbc/WSO2CarbonDB</Property>
<Property name="MaxUserNameListLength">100</Property>
<Property name="Disabled">false</Property>
<Property name="IsEmailUserName">false</Property>
<Property name="DomainCalculation">default</Property>
<Property name="PasswordDigest">SHA-256</Property>
<Property name="StoreSaltedPassword">true</Property>
<Property name="ReadGroups">true</Property>
<Property name="WriteGroups">true</Property>
<Property name="UserNameUniqueAcrossTenants">false</Property>
<Property name="PasswordJavaRegEx">^[\S]{5,30}$</Property>
<Property name="PasswordJavaScriptRegEx">^[\S]{5,30}$</Property>
<Property name="UsernameJavaRegEx">^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$</Property>
<Property name="UsernameJavaScriptRegEx">^[\S]{3,30}$</Property>
<Property name="RolenameJavaRegEx">^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$</Property>
<Property name="RolenameJavaScriptRegEx">^[\S]{3,30}$</Property>
<Property name="UserRolesCacheEnabled">true</Property>
<Property name="MaxRoleNameListLength">100</Property>
<Property name="MaxUserNameListLength">100</Property>
</UserStoreManager>
<UserStoreManager class="org.wso2.carbon.jdbc.sample.SampleJDBCUserStoreManager">
<Property name="ReadOnly">false</Property>
<Property name="dataSource">jdbc/SampleUserStore</Property>
<Property name="MaxUserNameListLength">100</Property>
<Property name="Disabled">false</Property>
<Property name="IsEmailUserName">false</Property>
<Property name="DomainCalculation">default</Property>
<Property name="PasswordDigest">SHA-256</Property>
<Property name="StoreSaltedPassword">true</Property>
<Property name="ReadGroups">true</Property>
<Property name="WriteGroups">true</Property>
<Property name="UserNameUniqueAcrossTenants">false</Property>
<Property name="PasswordJavaRegEx">^[\S]{5,30}$</Property>
<Property name="PasswordJavaScriptRegEx">^[\S]{5,30}$</Property>
<Property name="UsernameJavaRegEx">^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$</Property>
<Property name="UsernameJavaScriptRegEx">^[\S]{3,30}$</Property>
<Property name="RolenameJavaRegEx">^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$</Property>
<Property name="RolenameJavaScriptRegEx">^[\S]{3,30}$</Property>
<Property name="UserRolesCacheEnabled">true</Property>
<Property name="MaxRoleNameListLength">100</Property>
<Property name="MaxUserNameListLength">100</Property>
<Property name="DomainName">sample.com</Property>
<Property name="SelectUserSQL">SELECT * FROM CUSTOMER_DATA WHERE CUSTOMER_NAME=?</Property>
<Property name="UserFilterSQL">SELECT CUSTOMER_NAME FROM CUSTOMER_DATA WHERE CUSTOMER_NAME LIKE ? ORDER BY CUSTOMER_ID</Property>
<Property name="GetUserPropertiesForProfileSQL">SELECT EMAIL,AGE,STATUS FROM CUSTOMER_DATA WHERE CUSTOMER_NAME=?</Property>
</UserStoreManager>
<AuthorizationManager
class="org.wso2.carbon.user.core.authorization.JDBCAuthorizationManager">
<Property name="AdminRoleManagementPermissions">/permission</Property>
<Property name="AuthorizationCacheEnabled">true</Property>
</AuthorizationManager>
</Realm>
</UserManager>
[/sourcecode]
3. Same as you did in early post you have to place the mysql-connector-java-5.1.7-bin.jar and Sample_user_store-1.0.jar in to $IS_HOME/repository/component/libs
4. Start the Identity server and Sign in as admin.
5. Go to claim management.
Now you can see some Available Claim Dialects here. In the user store manager is using the http://wso2.org/claims so we need to add the new claim mapping on this.
5. Go to http://wso2.org/claims Dialect.
6. Add new Claim EMAIL
Here you need to specify the Mapped Attribute (s) as EMAIL because in our custom user store manager check the property name as "EMAIL","AGE","STATUS"
7. Add new Claim AGE
8. Add new Claim STATUS
9. Lets look at the users
And go to User profile
Now you can see the properties in the database is coming under user profile.
10. Now we need to use those properties and do some authorization. So we can easily move to XACML engine coming with the Identity server to do the needful. Here I'm not going to explain the behavior of the XACML Engine in Identity server but you can follow my early blog posts such as
Authentication and Authorization with WSO2ESB and WSO2IS
XACML Authorization
11. Now I'm going to create the XACML policy buy using the claims that we newly added.
You can see the claim names that we mapped early so you can select those from the UI.
Click on the policy name and go to source view of XACML policy.
and replace the Deny with Permit and update the policy.
12. Now enable the created policy as follows.
13. Go to Tryit and test your policy.
This is very basic example but when its coming to the real world example you can do so many things with this user store extensible facility. as well you can do all the above stuff with the use of web services which are exposed by WSO2 Identity Server.
Wednesday, April 3, 2013
How to write Custom JDBC user store manager with WSO2IS 4.1.1 alpha
Download id 4.1.1- alpha here
Lets think about real world business scenario, Simple company has their own database with Customer name and the password. now they need to do some security implementation with WSO2 Identity Server and they cannot duplicate those data as well as cannot change their db schema.
That means we cannot take those users and insert into the WSO2 IS database as well as they cannot change their DB schema to our WSO2 IS database schema. Don't worry WSO2 Identity server has capability to solve this issue. lets look at the solution with mysql DB.
Steps:
1. Plug the external db as secondary user store.
2. Create some roles in Identity Server and assign the users (coming from external DB).
3. Give the permission to the role.
4. Access the Identity server.
Custom DB Schema
[sourcecode language="sql"]
CREATE TABLE CUSTOMER_DATA (
CUSTOMER_ID INTEGER NOT NULL AUTO_INCREMENT,
CUSTOMER_NAME VARCHAR(255) NOT NULL,
PASSWORD VARCHAR(255) NOT NULL,
PRIMARY KEY (CUSTOMER_ID),
UNIQUE(CUSTOMER_NAME)
);
[/sourcecode]
1. First we have to write down the Custom JDBCUserStoreManager to compatible with the above schema. So you need to create a class with any name that you preferred and extends JDBCUserStoreManager. I have created class call SampleJDBCUserStoreManager.java (download mvn project here).
In my custom class I'm not going to override all methods in JDBCUserStoreManager because this user store is going to plug as read only mode.
2. Let's look at the master-datasource.xml
I have created two data source because I'm going to connect to the two user stores as primary and secondary. you bettor read my early blog post call (Multiple User Stores configuration in WSO2 Identity Server) but there is lot of api changes in 4.1.1 alpha.
[sourcecode language="xml"]
<datasources-configuration xmlns:svns="http://org.wso2.securevault/configuration">
<providers>
<provider>org.wso2.carbon.ndatasource.rdbms.RDBMSDataSourceReader</provider>
</providers>
<datasources>
<datasource>
<name>WSO2_CARBON_DB</name>
<description>The datasource used for registry</description>
<jndiConfig>
<name>jdbc/WSO2CarbonDB</name>
</jndiConfig>
<definition type="RDBMS">
<configuration>
<url>jdbc:mysql://localhost:3306/WSO2_CARBON</url>
<username>root</username>
<password>root</password>
<driverClassName>com.mysql.jdbc.Driver</driverClassName>
<maxActive>50</maxActive>
<maxWait>60000</maxWait>
<testOnBorrow>true</testOnBorrow>
<validationQuery>SELECT 1</validationQuery>
<validationInterval>30000</validationInterval>
</configuration>
</definition>
</datasource>
<datasource>
<name>Sample_DB</name>
<description>The datasource used for user manager</description>
<jndiConfig>
<name>jdbc/SampleUserStore</name>
</jndiConfig>
<definition type="RDBMS">
<configuration>
<url>jdbc:mysql://localhost:3306/custom_users</url>
<username>root</username>
<password>root</password>
<driverClassName>com.mysql.jdbc.Driver</driverClassName>
<maxActive>50</maxActive>
<maxWait>60000</maxWait>
<testOnBorrow>true</testOnBorrow>
<validationQuery>SELECT 1</validationQuery>
<validationInterval>30000</validationInterval>
</configuration>
</definition>
</datasource>
</datasources>
</datasources-configuration>
[/sourcecode]
3. Go to user-mgt.xml
Here I have define two user store manages and the first definition pic as primary user store manager form the Identity server.
The secondary one is the custom user store manager that i have written early.
[sourcecode language="xml"]
<UserManager>
<Realm>
<Configuration>
<AddAdmin>true</AddAdmin>
<AdminRole>admin</AdminRole>
<AdminUser>
<UserName>admin</UserName>
<Password>admin</Password>
</AdminUser>
<EveryOneRoleName>everyone</EveryOneRoleName> <!-- By default users in this role sees the registry root -->
<Property name="dataSource">jdbc/WSO2CarbonDB</Property>
<Property name="MultiTenantRealmConfigBuilder">org.wso2.carbon.user.core.config.multitenancy.SimpleRealmConfigBuilder</Property>
<!-- Use the following MultiTenantRealmConfigBuilder with LDAP based UserStoreManagers-->
<!--Property name="MultiTenantRealmConfigBuilder">org.wso2.carbon.user.core.config.multitenancy.CommonLDAPRealmConfigBuilder</Property-->
</Configuration>
<UserStoreManager class="org.wso2.carbon.user.core.jdbc.JDBCUserStoreManager">
<Property name="ReadOnly">false</Property>
<Property name="dataSource">jdbc/WSO2CarbonDB</Property>
<Property name="MaxUserNameListLength">100</Property>
<Property name="Disabled">false</Property>
<Property name="IsEmailUserName">false</Property>
<Property name="DomainCalculation">default</Property>
<Property name="PasswordDigest">SHA-256</Property>
<Property name="StoreSaltedPassword">true</Property>
<Property name="ReadGroups">true</Property>
<Property name="WriteGroups">true</Property>
<Property name="UserNameUniqueAcrossTenants">false</Property>
<Property name="PasswordJavaRegEx">^[\S]{5,30}$</Property>
<Property name="PasswordJavaScriptRegEx">^[\S]{5,30}$</Property>
<Property name="UsernameJavaRegEx">^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$</Property>
<Property name="UsernameJavaScriptRegEx">^[\S]{3,30}$</Property>
<Property name="RolenameJavaRegEx">^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$</Property>
<Property name="RolenameJavaScriptRegEx">^[\S]{3,30}$</Property>
<Property name="UserRolesCacheEnabled">true</Property>
<Property name="MaxRoleNameListLength">100</Property>
<Property name="MaxUserNameListLength">100</Property>
</UserStoreManager>
<UserStoreManager class="org.wso2.carbon.jdbc.sample.SampleJDBCUserStoreManager">
<Property name="ReadOnly">false</Property>
<Property name="dataSource">jdbc/SampleUserStore</Property>
<Property name="MaxUserNameListLength">100</Property>
<Property name="Disabled">false</Property>
<Property name="IsEmailUserName">false</Property>
<Property name="DomainCalculation">default</Property>
<Property name="PasswordDigest">SHA-256</Property>
<Property name="StoreSaltedPassword">true</Property>
<Property name="ReadGroups">true</Property>
<Property name="WriteGroups">true</Property>
<Property name="UserNameUniqueAcrossTenants">false</Property>
<Property name="PasswordJavaRegEx">^[\S]{5,30}$</Property>
<Property name="PasswordJavaScriptRegEx">^[\S]{5,30}$</Property>
<Property name="UsernameJavaRegEx">^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$</Property>
<Property name="UsernameJavaScriptRegEx">^[\S]{3,30}$</Property>
<Property name="RolenameJavaRegEx">^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$</Property>
<Property name="RolenameJavaScriptRegEx">^[\S]{3,30}$</Property>
<Property name="UserRolesCacheEnabled">true</Property>
<Property name="MaxRoleNameListLength">100</Property>
<Property name="MaxUserNameListLength">100</Property>
<Property name="DomainName">sample.com</Property>
<Property name="SelectUserSQL">SELECT * FROM CUSTOMER_DATA WHERE CUSTOMER_NAME=?</Property>
<Property name="UserFilterSQL">SELECT CUSTOMER_NAME FROM CUSTOMER_DATA WHERE CUSTOMER_NAME LIKE ? ORDER BY CUSTOMER_ID</Property>
</UserStoreManager>
<AuthorizationManager
class="org.wso2.carbon.user.core.authorization.JDBCAuthorizationManager">
<Property name="AdminRoleManagementPermissions">/permission</Property>
<Property name="AuthorizationCacheEnabled">true</Property>
</AuthorizationManager>
</Realm>
</UserManager>
[/sourcecode]
You can see I'm passing the custom SQLs as "SelectUserSQL" and "UserFilterSQL"
4. You need to put following jars in to the $IS_HOME/repository/component/libs
mysql-connector-java-5.1.7-bin.jar and Sample_user_store-1.0.jar
5. Now I'm going to start the Identity server and sign in as admin
6. Go to users then you can see the users coming from secondary user store as read only
7. Now we need to create the internal role because we cannot create the roles inside of the secondary user store manager due to read only mode.So you can do it as follows.
you have to give the permission to the created role
Now you can assign the users from secondary user store.
8. Login to the IS from the secondary users.
Lets think about real world business scenario, Simple company has their own database with Customer name and the password. now they need to do some security implementation with WSO2 Identity Server and they cannot duplicate those data as well as cannot change their db schema.
That means we cannot take those users and insert into the WSO2 IS database as well as they cannot change their DB schema to our WSO2 IS database schema. Don't worry WSO2 Identity server has capability to solve this issue. lets look at the solution with mysql DB.
Steps:
1. Plug the external db as secondary user store.
2. Create some roles in Identity Server and assign the users (coming from external DB).
3. Give the permission to the role.
4. Access the Identity server.
Custom DB Schema
[sourcecode language="sql"]
CREATE TABLE CUSTOMER_DATA (
CUSTOMER_ID INTEGER NOT NULL AUTO_INCREMENT,
CUSTOMER_NAME VARCHAR(255) NOT NULL,
PASSWORD VARCHAR(255) NOT NULL,
PRIMARY KEY (CUSTOMER_ID),
UNIQUE(CUSTOMER_NAME)
);
[/sourcecode]
1. First we have to write down the Custom JDBCUserStoreManager to compatible with the above schema. So you need to create a class with any name that you preferred and extends JDBCUserStoreManager. I have created class call SampleJDBCUserStoreManager.java (download mvn project here).
In my custom class I'm not going to override all methods in JDBCUserStoreManager because this user store is going to plug as read only mode.
2. Let's look at the master-datasource.xml
I have created two data source because I'm going to connect to the two user stores as primary and secondary. you bettor read my early blog post call (Multiple User Stores configuration in WSO2 Identity Server) but there is lot of api changes in 4.1.1 alpha.
[sourcecode language="xml"]
<datasources-configuration xmlns:svns="http://org.wso2.securevault/configuration">
<providers>
<provider>org.wso2.carbon.ndatasource.rdbms.RDBMSDataSourceReader</provider>
</providers>
<datasources>
<datasource>
<name>WSO2_CARBON_DB</name>
<description>The datasource used for registry</description>
<jndiConfig>
<name>jdbc/WSO2CarbonDB</name>
</jndiConfig>
<definition type="RDBMS">
<configuration>
<url>jdbc:mysql://localhost:3306/WSO2_CARBON</url>
<username>root</username>
<password>root</password>
<driverClassName>com.mysql.jdbc.Driver</driverClassName>
<maxActive>50</maxActive>
<maxWait>60000</maxWait>
<testOnBorrow>true</testOnBorrow>
<validationQuery>SELECT 1</validationQuery>
<validationInterval>30000</validationInterval>
</configuration>
</definition>
</datasource>
<datasource>
<name>Sample_DB</name>
<description>The datasource used for user manager</description>
<jndiConfig>
<name>jdbc/SampleUserStore</name>
</jndiConfig>
<definition type="RDBMS">
<configuration>
<url>jdbc:mysql://localhost:3306/custom_users</url>
<username>root</username>
<password>root</password>
<driverClassName>com.mysql.jdbc.Driver</driverClassName>
<maxActive>50</maxActive>
<maxWait>60000</maxWait>
<testOnBorrow>true</testOnBorrow>
<validationQuery>SELECT 1</validationQuery>
<validationInterval>30000</validationInterval>
</configuration>
</definition>
</datasource>
</datasources>
</datasources-configuration>
[/sourcecode]
3. Go to user-mgt.xml
Here I have define two user store manages and the first definition pic as primary user store manager form the Identity server.
The secondary one is the custom user store manager that i have written early.
[sourcecode language="xml"]
<UserManager>
<Realm>
<Configuration>
<AddAdmin>true</AddAdmin>
<AdminRole>admin</AdminRole>
<AdminUser>
<UserName>admin</UserName>
<Password>admin</Password>
</AdminUser>
<EveryOneRoleName>everyone</EveryOneRoleName> <!-- By default users in this role sees the registry root -->
<Property name="dataSource">jdbc/WSO2CarbonDB</Property>
<Property name="MultiTenantRealmConfigBuilder">org.wso2.carbon.user.core.config.multitenancy.SimpleRealmConfigBuilder</Property>
<!-- Use the following MultiTenantRealmConfigBuilder with LDAP based UserStoreManagers-->
<!--Property name="MultiTenantRealmConfigBuilder">org.wso2.carbon.user.core.config.multitenancy.CommonLDAPRealmConfigBuilder</Property-->
</Configuration>
<UserStoreManager class="org.wso2.carbon.user.core.jdbc.JDBCUserStoreManager">
<Property name="ReadOnly">false</Property>
<Property name="dataSource">jdbc/WSO2CarbonDB</Property>
<Property name="MaxUserNameListLength">100</Property>
<Property name="Disabled">false</Property>
<Property name="IsEmailUserName">false</Property>
<Property name="DomainCalculation">default</Property>
<Property name="PasswordDigest">SHA-256</Property>
<Property name="StoreSaltedPassword">true</Property>
<Property name="ReadGroups">true</Property>
<Property name="WriteGroups">true</Property>
<Property name="UserNameUniqueAcrossTenants">false</Property>
<Property name="PasswordJavaRegEx">^[\S]{5,30}$</Property>
<Property name="PasswordJavaScriptRegEx">^[\S]{5,30}$</Property>
<Property name="UsernameJavaRegEx">^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$</Property>
<Property name="UsernameJavaScriptRegEx">^[\S]{3,30}$</Property>
<Property name="RolenameJavaRegEx">^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$</Property>
<Property name="RolenameJavaScriptRegEx">^[\S]{3,30}$</Property>
<Property name="UserRolesCacheEnabled">true</Property>
<Property name="MaxRoleNameListLength">100</Property>
<Property name="MaxUserNameListLength">100</Property>
</UserStoreManager>
<UserStoreManager class="org.wso2.carbon.jdbc.sample.SampleJDBCUserStoreManager">
<Property name="ReadOnly">false</Property>
<Property name="dataSource">jdbc/SampleUserStore</Property>
<Property name="MaxUserNameListLength">100</Property>
<Property name="Disabled">false</Property>
<Property name="IsEmailUserName">false</Property>
<Property name="DomainCalculation">default</Property>
<Property name="PasswordDigest">SHA-256</Property>
<Property name="StoreSaltedPassword">true</Property>
<Property name="ReadGroups">true</Property>
<Property name="WriteGroups">true</Property>
<Property name="UserNameUniqueAcrossTenants">false</Property>
<Property name="PasswordJavaRegEx">^[\S]{5,30}$</Property>
<Property name="PasswordJavaScriptRegEx">^[\S]{5,30}$</Property>
<Property name="UsernameJavaRegEx">^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$</Property>
<Property name="UsernameJavaScriptRegEx">^[\S]{3,30}$</Property>
<Property name="RolenameJavaRegEx">^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$</Property>
<Property name="RolenameJavaScriptRegEx">^[\S]{3,30}$</Property>
<Property name="UserRolesCacheEnabled">true</Property>
<Property name="MaxRoleNameListLength">100</Property>
<Property name="MaxUserNameListLength">100</Property>
<Property name="DomainName">sample.com</Property>
<Property name="SelectUserSQL">SELECT * FROM CUSTOMER_DATA WHERE CUSTOMER_NAME=?</Property>
<Property name="UserFilterSQL">SELECT CUSTOMER_NAME FROM CUSTOMER_DATA WHERE CUSTOMER_NAME LIKE ? ORDER BY CUSTOMER_ID</Property>
</UserStoreManager>
<AuthorizationManager
class="org.wso2.carbon.user.core.authorization.JDBCAuthorizationManager">
<Property name="AdminRoleManagementPermissions">/permission</Property>
<Property name="AuthorizationCacheEnabled">true</Property>
</AuthorizationManager>
</Realm>
</UserManager>
[/sourcecode]
You can see I'm passing the custom SQLs as "SelectUserSQL" and "UserFilterSQL"
4. You need to put following jars in to the $IS_HOME/repository/component/libs
mysql-connector-java-5.1.7-bin.jar and Sample_user_store-1.0.jar
5. Now I'm going to start the Identity server and sign in as admin
6. Go to users then you can see the users coming from secondary user store as read only
7. Now we need to create the internal role because we cannot create the roles inside of the secondary user store manager due to read only mode.So you can do it as follows.
you have to give the permission to the created role
Now you can assign the users from secondary user store.
8. Login to the IS from the secondary users.
Monday, April 1, 2013
Simple Java Client to talk to Queues and Topics in IBM MQ 7.5
IBM MQ is one of Message Queue implementation heavily used for interprocess communication in the software industry.
So I just crated a simple java client to talk to Queues and Topics in the IBM MQ.
Here I'm going to talk to the IBM MQ through the ".binding" file provided by the IBM MQ installation.
1. First you need to install the IBM MQ (I'm using windows machine to Install the IBM MQ).
2. Open IBM WebSphere MQ Explorer and do the following
Create Queue Manager as mymgr
Create Local Queue as localq
Create Local Topic as localt
3. Go to C:\Program Files\IBM\WebSphere MQ\java\bin, and invoke IVT app by running the following command:
IVTRun.bat –nojndi
If successful the following will be displayed:
4. Run the following command:
IVTRun.bat -nojndi -client -m mymgr -host localhost -channel mychannel
If successful the following will be displayed:
5. Navigate to to C:\IBM\WebSphere MQ\java\bin directory, open 'JMSAdmin.config' file and edit the file as follows:
a. Uncomment the configuration for INITIAL_CONTEXT_FACTORY
ex: INITIAL_CONTEXT_FACTORY=com.sun.jndi.fscontext.RefFSContextFactory
b. Point to an empty folder for PROVIDER_URL - ex: PROVIDER_URL=file:/C:/JNDI-Directory
6. Create the default set of JNDI bindings by running the following command in the command prompt:
IVTSetup.bat
If successful the following will be displayed:
7. Let's use the JMSAdmin tool to make some modifications in the JNDI bindings
Navigate to the C:\IBM\WebSphere MQ\java\bin directory from the console and start jmsadmin by running the following command:
jmsadmin.bat
Run the following commands:
For Queue:
ALTER QCF(ivtQCF) TRANSPORT(CLIENT)
ALTER QCF(ivtQCF) QMGR(mymgr)
For Topics:
ALTER TCF(ivtTCF) TRANSPORT(CLIENT)
ALTER TCF(ivtTCF) QMGR(mymgr)
8. Go to the "JMS Administered Objects" and select Add initial context. Then select the "File system" and enter the JNDI directory path. Then you can view all created Queues and Topics.
9. Now you can download the Java project here and open it form JIdea and make the following changes and run the client.
Replace your JNDI-Directory path
Replace the Queue Name and Queue connection factory name
Replace the Topic Name and Topic connection factory name
So I just crated a simple java client to talk to Queues and Topics in the IBM MQ.
Here I'm going to talk to the IBM MQ through the ".binding" file provided by the IBM MQ installation.
1. First you need to install the IBM MQ (I'm using windows machine to Install the IBM MQ).
2. Open IBM WebSphere MQ Explorer and do the following
Create Queue Manager as mymgr
Create Local Queue as localq
Create Local Topic as localt
3. Go to C:\Program Files\IBM\WebSphere MQ\java\bin, and invoke IVT app by running the following command:
IVTRun.bat –nojndi
If successful the following will be displayed:
4. Run the following command:
IVTRun.bat -nojndi -client -m mymgr -host localhost -channel mychannel
If successful the following will be displayed:
5. Navigate to to C:\IBM\WebSphere MQ\java\bin directory, open 'JMSAdmin.config' file and edit the file as follows:
a. Uncomment the configuration for INITIAL_CONTEXT_FACTORY
ex: INITIAL_CONTEXT_FACTORY=com.sun.jndi.fscontext.RefFSContextFactory
b. Point to an empty folder for PROVIDER_URL - ex: PROVIDER_URL=file:/C:/JNDI-Directory
6. Create the default set of JNDI bindings by running the following command in the command prompt:
IVTSetup.bat
If successful the following will be displayed:
7. Let's use the JMSAdmin tool to make some modifications in the JNDI bindings
Navigate to the C:\IBM\WebSphere MQ\java\bin directory from the console and start jmsadmin by running the following command:
jmsadmin.bat
Run the following commands:
For Queue:
ALTER QCF(ivtQCF) TRANSPORT(CLIENT)
ALTER QCF(ivtQCF) QMGR(mymgr)
For Topics:
ALTER TCF(ivtTCF) TRANSPORT(CLIENT)
ALTER TCF(ivtTCF) QMGR(mymgr)
8. Go to the "JMS Administered Objects" and select Add initial context. Then select the "File system" and enter the JNDI directory path. Then you can view all created Queues and Topics.
9. Now you can download the Java project here and open it form JIdea and make the following changes and run the client.
Replace your JNDI-Directory path
Replace the Queue Name and Queue connection factory name
Replace the Topic Name and Topic connection factory name
Subscribe to:
Posts (Atom)