Does the Apache Shiro Authentication Framework support the use of the bCrypt password hashing algorithm? If not, is there a way to get it working with Shiro?
Are there any other Authentication frameworks like Shiro supporting bCrypt, other than Spring Security?
There is an open feature request about exactly this on Apache Shiro JIRA (SHIRO-290).
According to this issue, it will be implemented in version 1.3.0.
Our solution: (from org.soluvas.security.shiro.BCryptPasswordService)
package org.soluvas.security.shiro;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashingPasswordService;
import org.apache.shiro.authc.credential.PasswordService;
import org.apache.shiro.crypto.hash.Hash;
import org.mindrot.jbcrypt.BCrypt;
import org.soluvas.security.SecurityException;
/**
* Inspired by Coderwall: Using BCrypt with Shiro. Please vote for SHIRO-290.
*
* <p>Requires:</p>
*
* <pre>{#code
* <dependency>
* <groupId>de.svenkubiak</groupId>
* <artifactId>jBCrypt</artifactId>
* <version>0.4.1</version>
* </dependency>
* }</pre>
*
* <p>Usage:</p>
*
* <pre>{#code
* #Bean
* public JdbcRealm jdbcRealm() {
* final JdbcRealm jdbcRealm = new JdbcRealm();
* jdbcRealm.setDataSource(dataSource);
* // jdbcRealm.setAuthenticationQuery(Person2.SHIRO_AUTHENTICATION_QUERY);
* final PasswordMatcher passwordMatcher = new PasswordMatcher();
* passwordMatcher.setPasswordService(new BCryptPasswordService());
* jdbcRealm.setCredentialsMatcher(passwordMatcher);
* return jdbcRealm;
* }
* }</pre>
*/
public class BCryptPasswordService implements PasswordService {
#Override
public String encryptPassword(Object plaintextPassword) throws IllegalArgumentException {
final String str;
if (plaintextPassword instanceof char[]) {
str = new String((char[]) plaintextPassword);
} else if (plaintextPassword instanceof String) {
str = (String) plaintextPassword;
} else {
throw new SecurityException("Unsupported password type: " + plaintextPassword.getClass().getName());
}
return BCrypt.hashpw(str, BCrypt.gensalt());
}
#Override
public boolean passwordsMatch(Object submittedPlaintext, String encrypted) {
return BCrypt.checkpw(new String((char[]) submittedPlaintext), encrypted);
}
}
Related
I need to make a Soap client in java for the EU tax id service.
I mamanged to generate the code from the WSDL using wsimport. My problem is that cannot figure out how to use it. More specifically, how do I make a Soap call to the service so I can validate the tax id?
I tried even multiple ways using code generated from SOAP UI, code from Intellij, etc. They are all quite different and I am kinda stuck into this. Could anyone light me up, please? Thanks!
It seems rather difficult for me and I already spent so many hours on this without a result. I have also tried al the tutorials I could find on google. I am guessing an answer on this would help many in the future.
Here's the generated code:
CheckTinService.java:
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebEndpoint;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;
/**
* This class was generated by the JAX-WS RI.
* JAX-WS RI 2.2.4-b01
* Generated source version: 2.2
*
*/
#WebServiceClient(name = "checkTinService", targetNamespace = "urn:ec.europa.eu:taxud:tin:services:checkTin", wsdlLocation = "https://ec.europa.eu/taxation_customs/tin/checkTinService.wsdl")
public class CheckTinService
extends Service
{
private final static URL CHECKTINSERVICE_WSDL_LOCATION;
private final static WebServiceException CHECKTINSERVICE_EXCEPTION;
private final static QName CHECKTINSERVICE_QNAME = new QName("urn:ec.europa.eu:taxud:tin:services:checkTin", "checkTinService");
static {
URL url = null;
WebServiceException e = null;
try {
url = new URL("https://ec.europa.eu/taxation_customs/tin/checkTinService.wsdl");
} catch (MalformedURLException ex) {
e = new WebServiceException(ex);
}
CHECKTINSERVICE_WSDL_LOCATION = url;
CHECKTINSERVICE_EXCEPTION = e;
}
public CheckTinService() {
super(__getWsdlLocation(), CHECKTINSERVICE_QNAME);
}
public CheckTinService(WebServiceFeature... features) {
super(__getWsdlLocation(), CHECKTINSERVICE_QNAME);
}
public CheckTinService(URL wsdlLocation) {
super(wsdlLocation, CHECKTINSERVICE_QNAME);
}
public CheckTinService(URL wsdlLocation, WebServiceFeature... features) {
super(wsdlLocation, CHECKTINSERVICE_QNAME);
}
public CheckTinService(URL wsdlLocation, QName serviceName) {
super(wsdlLocation, serviceName);
}
public CheckTinService(URL wsdlLocation, QName serviceName, WebServiceFeature... features) {
super(wsdlLocation, serviceName);
}
/**
*
* #return
* returns CheckTinPortType
*/
#WebEndpoint(name = "checkTinPort")
public CheckTinPortType getCheckTinPort() {
return super.getPort(new QName("urn:ec.europa.eu:taxud:tin:services:checkTin", "checkTinPort"), CheckTinPortType.class);
}
/**
*
* #param features
* A list of {#link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the <code>features</code> parameter will have their default values.
* #return
* returns CheckTinPortType
*/
#WebEndpoint(name = "checkTinPort")
public CheckTinPortType getCheckTinPort(WebServiceFeature... features) {
return super.getPort(new QName("urn:ec.europa.eu:taxud:tin:services:checkTin", "checkTinPort"), CheckTinPortType.class, features);
}
private static URL __getWsdlLocation() {
if (CHECKTINSERVICE_EXCEPTION!= null) {
throw CHECKTINSERVICE_EXCEPTION;
}
return CHECKTINSERVICE_WSDL_LOCATION;
}
}
CheckTinPortType.java
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.ws.Holder;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
import eu.europa.ec.taxud.tin.services.checktin.types.ObjectFactory;
/**
* This class was generated by the JAX-WS RI.
* JAX-WS RI 2.2.4-b01
* Generated source version: 2.2
*
*/
#WebService(name = "checkTinPortType", targetNamespace = "urn:ec.europa.eu:taxud:tin:services:checkTin")
#XmlSeeAlso({
ObjectFactory.class
})
public interface CheckTinPortType {
/**
*
* #param tinNumber
* #param countryCode
* #param validStructure
* #param requestDate
* #param validSyntax
*/
#WebMethod
#RequestWrapper(localName = "checkTin", targetNamespace = "urn:ec.europa.eu:taxud:tin:services:checkTin:types", className = "eu.europa.ec.taxud.tin.services.checktin.types.CheckTin")
#ResponseWrapper(localName = "checkTinResponse", targetNamespace = "urn:ec.europa.eu:taxud:tin:services:checkTin:types", className = "eu.europa.ec.taxud.tin.services.checktin.types.CheckTinResponse")
public void checkTin(
#WebParam(name = "countryCode", targetNamespace = "urn:ec.europa.eu:taxud:tin:services:checkTin:types", mode = WebParam.Mode.INOUT)
Holder<String> countryCode,
#WebParam(name = "tinNumber", targetNamespace = "urn:ec.europa.eu:taxud:tin:services:checkTin:types", mode = WebParam.Mode.INOUT)
Holder<String> tinNumber,
#WebParam(name = "requestDate", targetNamespace = "urn:ec.europa.eu:taxud:tin:services:checkTin:types", mode = WebParam.Mode.OUT)
Holder<XMLGregorianCalendar> requestDate,
#WebParam(name = "validStructure", targetNamespace = "urn:ec.europa.eu:taxud:tin:services:checkTin:types", mode = WebParam.Mode.OUT)
Holder<Boolean> validStructure,
#WebParam(name = "validSyntax", targetNamespace = "urn:ec.europa.eu:taxud:tin:services:checkTin:types", mode = WebParam.Mode.OUT)
Holder<Boolean> validSyntax);
}
ObjectFactory.java:
import com.exiqon.core.eu.europa.ec.taxud.tin.services.checktin.types.CheckTin;
import com.exiqon.core.eu.europa.ec.taxud.tin.services.checktin.types.CheckTinResponse;
import javax.xml.bind.annotation.XmlRegistry;
/**
* This object contains factory methods for each
* Java content interface and Java element interface
* generated in the eu.europa.ec.taxud.tin.services.checktin.types package.
* <p>An ObjectFactory allows you to programatically
* construct new instances of the Java representation
* for XML content. The Java representation of XML
* content can consist of schema derived interfaces
* and classes representing the binding of schema
* type definitions, element declarations and model
* groups. Factory methods for each of these are
* provided in this class.
*
*/
#XmlRegistry
public class ObjectFactory {
/**
* Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: eu.europa.ec.taxud.tin.services.checktin.types
*
*/
public ObjectFactory() {
}
/**
* Create an instance of {#link eu.europa.ec.taxud.tin.services.checktin.types.CheckTin }
*
*/
public CheckTin createCheckTin() {
return new CheckTin();
}
/**
* Create an instance of {#link CheckTinResponse }
*
*/
public CheckTinResponse createCheckTinResponse() {
return new CheckTinResponse();
}
}
CheckTinResponse.java:
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.datatype.XMLGregorianCalendar;
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="countryCode" type="{http://www.w3.org/2001/XMLSchema}string"/>
* <element name="tinNumber" type="{http://www.w3.org/2001/XMLSchema}string"/>
* <element name="requestDate" type="{http://www.w3.org/2001/XMLSchema}date"/>
* <element name="validStructure" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
* <element name="validSyntax" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"countryCode",
"tinNumber",
"requestDate",
"validStructure",
"validSyntax"
})
#XmlRootElement(name = "checkTinResponse")
public class CheckTinResponse {
#XmlElement(required = true)
protected String countryCode;
#XmlElement(required = true)
protected String tinNumber;
#XmlElement(required = true)
#XmlSchemaType(name = "date")
protected XMLGregorianCalendar requestDate;
protected boolean validStructure;
protected Boolean validSyntax;
/**
* Gets the value of the countryCode property.
*
* #return
* possible object is
* {#link String }
*
*/
public String getCountryCode() {
return countryCode;
}
/**
* Sets the value of the countryCode property.
*
* #param value
* allowed object is
* {#link String }
*
*/
public void setCountryCode(String value) {
this.countryCode = value;
}
/**
* Gets the value of the tinNumber property.
*
* #return
* possible object is
* {#link String }
*
*/
public String getTinNumber() {
return tinNumber;
}
/**
* Sets the value of the tinNumber property.
*
* #param value
* allowed object is
* {#link String }
*
*/
public void setTinNumber(String value) {
this.tinNumber = value;
}
/**
* Gets the value of the requestDate property.
*
* #return
* possible object is
* {#link XMLGregorianCalendar }
*
*/
public XMLGregorianCalendar getRequestDate() {
return requestDate;
}
/**
* Sets the value of the requestDate property.
*
* #param value
* allowed object is
* {#link XMLGregorianCalendar }
*
*/
public void setRequestDate(XMLGregorianCalendar value) {
this.requestDate = value;
}
/**
* Gets the value of the validStructure property.
*
*/
public boolean isValidStructure() {
return validStructure;
}
/**
* Sets the value of the validStructure property.
*
*/
public void setValidStructure(boolean value) {
this.validStructure = value;
}
/**
* Gets the value of the validSyntax property.
*
* #return
* possible object is
* {#link Boolean }
*
*/
public Boolean isValidSyntax() {
return validSyntax;
}
/**
* Sets the value of the validSyntax property.
*
* #param value
* allowed object is
* {#link Boolean }
*
*/
public void setValidSyntax(Boolean value) {
this.validSyntax = value;
}
}
CheckTin.java:
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="countryCode" type="{http://www.w3.org/2001/XMLSchema}string"/>
* <element name="tinNumber" type="{http://www.w3.org/2001/XMLSchema}string"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"countryCode",
"tinNumber"
})
#XmlRootElement(name = "checkTin")
public class CheckTin {
#XmlElement(required = true)
protected String countryCode;
#XmlElement(required = true)
protected String tinNumber;
/**
* Gets the value of the countryCode property.
*
* #return
* possible object is
* {#link String }
*
*/
public String getCountryCode() {
return countryCode;
}
/**
* Sets the value of the countryCode property.
*
* #param value
* allowed object is
* {#link String }
*
*/
public void setCountryCode(String value) {
this.countryCode = value;
}
/**
* Gets the value of the tinNumber property.
*
* #return
* possible object is
* {#link String }
*
*/
public String getTinNumber() {
return tinNumber;
}
/**
* Sets the value of the tinNumber property.
*
* #param value
* allowed object is
* {#link String }
*
*/
public void setTinNumber(String value) {
this.tinNumber = value;
}
}
sample client code.
public class WsTest {
public static void main(String[] args) {
try {
CheckTinService checkTinService = new CheckTinService();
CheckTinPortType portType = checkTinService.getPort(CheckTinPortType.class);
Holder<String> code = new Holder<String>("DE");
Holder<String> tin = new Holder<String>("12346789");
Holder<XMLGregorianCalendar> requestDate = new Holder<>();
Holder<Boolean> validStructure = new Holder<>();
Holder<Boolean> validSyntax = new Holder<>();
portType.checkTin(code, tin, requestDate, validStructure, validSyntax);
System.out.println("requestDate : " + requestDate.value);
System.out.println("validStructure : " + validStructure.value);
System.out.println("validSyntax : " + validSyntax.value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
you can also add handler for response soap message.
or from soap UI : send below request
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:ec.europa.eu:taxud:tin:services:checkTin:types">
<soapenv:Header/>
<soapenv:Body>
<urn:checkTin>
<urn:countryCode>DE</urn:countryCode>
<urn:tinNumber>12346789</urn:tinNumber>
</urn:checkTin>
</soapenv:Body>
</soapenv:Envelope>
What's the problem here?
Get a CheckTinPortType by calling a properly initialized CheckTinService's getCheckTinPort(), and use that to perform the call.
All the necessary classes are generated, you just need to perform the checkTin() call now with the appropriate parameters.
I am using the socialauth library following this tutorial:
https://github.com/3pillarlabs/socialauth/wiki/Getting-Started-with-implementing-SocialAuth
Everything works find, I just do not understand where/what to store after the end of step 3. I mean I do not want to force the user to login every click. I tried to figure this out from the examples but I could not ....
Here is what I have:
#WebServlet("/success")
public class AfterOAuth extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
// get the auth provider manager from session
SocialAuthManager manager = (SocialAuthManager) req.getSession().getAttribute("authManager");
// call connect method of manager which returns the provider object.
// Pass request parameter map while calling connect method.
Map<String, String> paramsMap = SocialAuthUtil.getRequestParametersMap(req);
AuthProvider provider = manager.connect(paramsMap);
// get profile
Profile p = provider.getUserProfile();
// you can obtain profile information
resp.getOutputStream().print(p.getFirstName());
// OK, everything is fine by now what should I store in my Session?
} catch (Exception e) {
throw new ServletException(e);
}
}
}
Ok, I found a solution by using the provided CDI Class and overwrote simply the init() and servlet sections to so:
package com.test.oauth;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Properties;
import javax.enterprise.context.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import config.KicEngineRootRessourceLoader;
import org.apache.log4j.Logger;
import org.brickred.socialauth.AuthProvider;
import org.brickred.socialauth.AuthProviderFactory;
import org.brickred.socialauth.Contact;
import org.brickred.socialauth.Profile;
import org.brickred.socialauth.SocialAuthConfig;
import org.brickred.socialauth.SocialAuthManager;
import org.brickred.socialauth.util.SocialAuthUtil;
/**
* Created by kic on 19.02.15.
*/
#Named("socialauth")
#SessionScoped
public class SocialAuth implements Serializable {
/**
* Serial version UID generated by Eclipse
*/
private static final long serialVersionUID = 1789108831048043099L;
private static final Logger log = Logger.getLogger( SocialAuth.class);
private String id;
private Profile profile;
private AuthProvider provider;
private String status;
private String viewUrl;
private SocialAuthManager manager;
private SocialAuthConfig config;
public void init() {
id = null;
provider = null;
config = new SocialAuthConfig().getDefault();
try {
Properties oauth = new Properties();
KicEngineRootRessourceLoader.loadProperties(oauth, "oauth_consumer");
config.load(oauth);
manager = new SocialAuthManager();
manager.setSocialAuthConfig(config);
} catch (Exception e) {
e.printStackTrace();
}
}
public SocialAuth() {
init();
}
public String getId() {
return id;
}
/**
* Sets the authentication provider. It is mandatory to do this before
* calling login
*
* #param id
* Can either have values facebook, foursquare, google, hotmail,
* linkedin, myspace, twitter, yahoo OR an OpenID URL
*/
public void setId(final String id) {
this.id = id;
}
/**
* Sets the view URL to which the user will be redirected after
* authentication
*
* #param viewUrl
* Relative URL of the view, for example "/openid.xhtml"
*/
public void setViewUrl(final String viewUrl) {
this.viewUrl = viewUrl;
}
/**
* Gets the relative URL of the view to which user will be redirected after
* authentication
*
* #return relative URL of the view
*/
public String getViewUrl() {
return viewUrl;
}
/**
* This is the most important action. It redirects the browser to an
* appropriate URL which will be used for authentication with the provider
* you set using setId()
*
* #throws Exception
*/
public void login(HttpServletRequest req, HttpServletResponse resp) throws Exception {
//String url = manager.getAuthenticationUrl(req.getParameter("provider"), successUrl);
String returnToUrl = viewUrl;
String url = manager.getAuthenticationUrl(id, returnToUrl);
// Store in session
req.getSession().setAttribute("authManager", manager);
// redirect
log.info("Redirecting to:" + url);
resp.sendRedirect(url);
}
/**
* Verifies the user when the external provider redirects back to our
* application
*
* #throws Exception
*/
public void connect(HttpServletRequest request) throws Exception {
provider = manager.connect(SocialAuthUtil.getRequestParametersMap(request));
profile= provider.getUserProfile();
}
/**
* Reinitializes the bean
*/
public void logout() {
init();
}
/**
* Returns the Profile information for the user. Should be called only after
* loginImmediately()
*
* #return Profile of the user
*/
public Profile getProfile() {
return profile;
}
/**
* Status of the user to be updated on a provider like Facebook or Twitter.
* Remember this will not give us the current status of the user
*
* #return status message to be updated
*/
public String getStatus() {
return status;
}
/**
* Status of the user to be updated on a provider like Facebook or Twitter.
* To actually update the status, call updateStatus action.
*
* #param status
*/
public void setStatus(final String status) {
this.status = status;
}
/**
* Updates the status on the given provider. Exception will be thrown if the
* provider does not provide this facility
*/
public void updateStatus() throws Exception {
provider.updateStatus(status);
}
/**
* Gets the list of contacts available from the provider. This may be used
* to import contacts of any user in your web application from your chosen
* provider like Gmail, Yahoo or Hotmail
*
* #return list of contacts
*/
public List<Contact> getContactList() throws Exception {
return provider.getContactList();
}
/**
* Retrieves the user profile from the provider.
*
* #return Profile object containing the profile information.
* #throws Exception
*/
public Profile getUserProfile() throws Exception {
return provider.getUserProfile();
}
}
Now I simply can use #Inject SocialAuth wherever needed.
While trying to run the code bellow to gain a SAML token (taken from VMWare samples to authenticate with SSO server) I got the following exception.
From some reason the request version 'http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue' and namespace 'http://docs.oasis-open.org/ws-sx/ws-trust/200512' are not supported.
Appreciate your help...
Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: Request version 'http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue' and namespace 'http://docs.oasis-open.org/ws-sx/ws-trust/200512' are not supported
at com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:178)
at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:125)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:108)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:135)
at com.sun.proxy.$Proxy40.issue(Unknown Source)
at com.vmware.sso.client.samples.AcquireBearerTokenByUserCredentialSample.getToken(AcquireBearerTokenByUserCredentialSample.java:178)
at com.vmware.sso.client.samples.AcquireBearerTokenByUserCredentialSample.main(AcquireBearerTokenByUserCredentialSample.java:210)
package com.vmware.sso.client.samples;
import java.util.GregorianCalendar;
import java.util.Map;
import java.util.TimeZone;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.ws.BindingProvider;
import org.oasis_open.docs.ws_sx.ws_trust._200512.LifetimeType;
import org.oasis_open.docs.ws_sx.ws_trust._200512.RenewingType;
import org.oasis_open.docs.ws_sx.ws_trust._200512.RequestSecurityTokenType;
import org.oasis_open.docs.wss._2004._01.oasis_200401_wss_wssecurity_utility_1_0.AttributedDateTime;
import org.w3c.dom.Element;
import com.rsa.names._2009._12.product.riat.wsdl.STSService;
import com.rsa.names._2009._12.product.riat.wsdl.STSServicePortType;
import com.vmware.sso.client.soaphandlers.HeaderHandlerResolver;
import com.vmware.sso.client.soaphandlers.SamlTokenExtractionHandler;
import com.vmware.sso.client.soaphandlers.TimeStampHandler;
import com.vmware.sso.client.soaphandlers.UserCredentialHandler;
import com.vmware.sso.client.utils.Utils;
/**
* This sample illustrates acquiring a bearer token from SSO server by passing
* the username and password of the user
*
* <pre>
* <b>Usage:</b>
* run.bat com.vmware.sso.client.samples.AcquireBearerTokenByUserCredentialSample [sso url] [username] [password]
* </pre>
*
* #author Ecosystem Engineering
*/
public class AcquireBearerTokenByUserCredentialSample {
/**
* #param args
* {#link String} array containing the following values in the
* below order: <li>SSO server url e.g. https://[Host Name or IP
* Address]:8444/ims/STSService</li> <li>username</li> <li>
* password</li>
* #return {#link Element} representing the Token issued
* #throws DatatypeConfigurationException
*/
public static Element getToken(String[] args)
throws DatatypeConfigurationException {
/* Instantiating the STSService */
STSService stsService = new STSService();
/*
* Instantiating the HeaderHandlerResolver. This is required to provide
* the capability of modifying the SOAP headers and the SOAP message in
* general for various requests via the different handlers. For
* different kinds of requests to SSO server one needs to follow the
* WS-Trust guidelines to provide the required SOAP message structure.
*/
HeaderHandlerResolver headerResolver = new HeaderHandlerResolver();
/*
* For this specific case we need the following header elements wrapped
* in the security tag.
*
* 1. Timestamp containing the request's creation and expiry time
*
* 2. UsernameToken containing the username/password
*/
/* Adding the Timestamp via TimeStampHandler */
headerResolver.addHandler(new TimeStampHandler());
/* Adding the UsernameToken via UserCredentialHandler */
UserCredentialHandler ucHandler = new UserCredentialHandler(args[1],
args[2]);
SamlTokenExtractionHandler sbHandler = new SamlTokenExtractionHandler();
headerResolver.addHandler(ucHandler);
headerResolver.addHandler(sbHandler);
/*
* Set the handlerResolver for the STSService to the
* HeaderHandlerResolver created above
*/
stsService.setHandlerResolver(headerResolver);
/*
* Retrieve the STSServicePort from the STSServicePortType object Note:
* All the required handlerResolvers need to be set in the
* STSServicePortType object before you retrieve the STSService instance
*/
STSServicePortType stsPort = stsService.getSTSServicePort();
/*
* Construct the SOAP body for the request. RequestSecurityTokenType is
* the parameter type that is passed to the "acquire" method. However,
* based on what kind of token (bearer or holder-of-key type) and by
* what means (aka username/password, certificate, or existing token) we
* want to acquire the token, different elements need to be populated
*/
RequestSecurityTokenType tokenType = new RequestSecurityTokenType();
/*
* For this request we need at least the following element in the
* RequestSecurityTokenType set
*
* 1. Lifetime - represented by LifetimeType which specifies the
* lifetime for the token to be issued
*
* 2. Tokentype - "urn:oasis:names:tc:SAML:2.0:assertion", which is the
* class that models the requested token
*
* 3. RequestType -
* "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue", as we want
* to get a token issued
*
* 4. KeyType -
* "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer",
* representing the kind of key the token will have. There are two
* options namely bearer and holder-of-key
*
* 5. SignatureAlgorithm -
* "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", representing the
* algorithm used for generating signature
*
* 6. Renewing - represented by the RenewingType which specifies whether
* the token is renewable or not
*/
LifetimeType lifetime = new LifetimeType();
DatatypeFactory dtFactory = DatatypeFactory.newInstance();
GregorianCalendar cal = new GregorianCalendar(
TimeZone.getTimeZone("GMT"));
XMLGregorianCalendar xmlCalendar = dtFactory
.newXMLGregorianCalendar(cal);
AttributedDateTime created = new AttributedDateTime();
created.setValue(xmlCalendar.toXMLFormat());
AttributedDateTime expires = new AttributedDateTime();
xmlCalendar.add(dtFactory.newDuration(30 * 60 * 1000));
expires.setValue(xmlCalendar.toXMLFormat());
lifetime.setCreated(created);
lifetime.setExpires(expires);
tokenType.setTokenType("urn:oasis:names:tc:SAML:2.0:assertion");
tokenType
.setRequestType("http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue");
tokenType.setLifetime(lifetime);
tokenType
.setKeyType("http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer");
tokenType
.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
RenewingType renewing = new RenewingType();
renewing.setAllow(Boolean.FALSE);
renewing.setOK(Boolean.FALSE); // WS-Trust Profile: MUST be set to false
tokenType.setRenewing(renewing);
/* Set the endpoint address for the request */
Map<String, Object> reqContext = ((BindingProvider) stsPort)
.getRequestContext();
reqContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, args[0]);
/*
* Invoke the "issue" method on the STSService object to acquire the
* token from SSO Server
*/
stsPort.issue(tokenType);
// SamlTokenExtractionHandler will now contain the raw SAML token for
// further consumption
return sbHandler.getToken();
}
private static void printUsage() {
System.out
.println("run.bat com.vmware.sso.client.samples.AcquireBearerTokenByUserCredentialSample [sso url] [username] [password]");
}
public static void main(String[] args)
throws DatatypeConfigurationException {
if (args.length < 3) {
printUsage();
return;
}
HostnameVerifier hv = new HostnameVerifier() {
#Override
public boolean verify(String urlHostName, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);
Utils.trustAllHttpsCertificates();
System.out.println("Aquiring a bearer token by using user credentials");
Utils.printToken(getToken(args));
}
}
The reason I got the error was pointing the wrong SSO URL
The right address is
https://SSO-SERVER:7444/ims/STSService
I was looking for a Chrome Extension which can intercept the download whenever we click on a PDF link or on a link that spawns a PDF at server end programmatically. One way of doing it was Selenium Browser Profiling, I found this particular code. I want Selenium to download the PDF file and rename it according to the strings i pass from the JAVA program.
How can i use this code to download code and hook it up it with my program. It should trigger this whenever i execute a command like this:-
**driver.findElement(By.xpath("//a[contains(#href,\"/bbtobs/bbtolbext/statements/savepdf?type=current&AccountIndex=0\")]")).click();**
CODE-
package com.lazerycode.selenium.filedownloader;
import org.apache.commons.io.FileUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.log4j.Logger;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Set;
public class FileDownloader {
private static final Logger LOG = Logger.getLogger(FileDownloader.class);
private WebDriver driver;
private String localDownloadPath = System.getProperty("java.io.tmpdir");
private boolean followRedirects = true;
private boolean mimicWebDriverCookieState = true;
private int httpStatusOfLastDownloadAttempt = 0;
public FileDownloader(WebDriver driverObject) {
this.driver = driverObject;
}
/**
* Specify if the FileDownloader class should follow redirects when trying to download a file
*
* #param value
*/
public void followRedirectsWhenDownloading(boolean value) {
this.followRedirects = value;
}
/**
* Get the current location that files will be downloaded to.
*
* #return The filepath that the file will be downloaded to.
*/
public String localDownloadPath() {
return this.localDownloadPath;
}
/**
* Set the path that files will be downloaded to.
*
* #param filePath The filepath that the file will be downloaded to.
*/
public void localDownloadPath(String filePath) {
this.localDownloadPath = filePath;
}
/**
* Download the file specified in the href attribute of a WebElement
*
* #param element
* #return
* #throws Exception
*/
public String downloadFile(WebElement element) throws Exception {
return downloader(element, "href");
}
/**
* Download the image specified in the src attribute of a WebElement
*
* #param element
* #return
* #throws Exception
*/
public String downloadImage(WebElement element) throws Exception {
return downloader(element, "src");
}
/**
* Gets the HTTP status code of the last download file attempt
*
* #return
*/
public int getHTTPStatusOfLastDownloadAttempt() {
return this.httpStatusOfLastDownloadAttempt;
}
/**
* Mimic the cookie state of WebDriver (Defaults to true)
* This will enable you to access files that are only available when logged in.
* If set to false the connection will be made as an anonymouse user
*
* #param value
*/
public void mimicWebDriverCookieState(boolean value) {
this.mimicWebDriverCookieState = value;
}
/**
* Load in all the cookies WebDriver currently knows about so that we can mimic the browser cookie state
*
* #param seleniumCookieSet
* #return
*/
private BasicCookieStore mimicCookieState(Set seleniumCookieSet) {
BasicCookieStore mimicWebDriverCookieStore = new BasicCookieStore();
for (Cookie seleniumCookie : seleniumCookieSet) {
BasicClientCookie duplicateCookie = new BasicClientCookie(seleniumCookie.getName(), seleniumCookie.getValue());
duplicateCookie.setDomain(seleniumCookie.getDomain());
duplicateCookie.setSecure(seleniumCookie.isSecure());
duplicateCookie.setExpiryDate(seleniumCookie.getExpiry());
duplicateCookie.setPath(seleniumCookie.getPath());
mimicWebDriverCookieStore.addCookie(duplicateCookie);
}
return mimicWebDriverCookieStore;
}
/**
* Perform the file/image download.
*
* #param element
* #param attribute
* #return
* #throws IOException
* #throws NullPointerException
*/
private String downloader(WebElement element, String attribute) throws IOException, NullPointerException, URISyntaxException {
String fileToDownloadLocation = element.getAttribute(attribute);
if (fileToDownloadLocation.trim().equals("")) throw new NullPointerException("The element you have specified does not link to anything!");
URL fileToDownload = new URL(fileToDownloadLocation);
File downloadedFile = new File(this.localDownloadPath + fileToDownload.getFile().replaceFirst("/|\\\\", ""));
if (downloadedFile.canWrite() == false) downloadedFile.setWritable(true);
HttpClient client = new DefaultHttpClient();
BasicHttpContext localContext = new BasicHttpContext();
LOG.info("Mimic WebDriver cookie state: " + this.mimicWebDriverCookieState);
if (this.mimicWebDriverCookieState) {
localContext.setAttribute(ClientContext.COOKIE_STORE, mimicCookieState(this.driver.manage().getCookies()));
}
HttpGet httpget = new HttpGet(fileToDownload.toURI());
HttpParams httpRequestParameters = httpget.getParams();
httpRequestParameters.setParameter(ClientPNames.HANDLE_REDIRECTS, this.followRedirects);
httpget.setParams(httpRequestParameters);
LOG.info("Sending GET request for: " + httpget.getURI());
HttpResponse response = client.execute(httpget, localContext);
this.httpStatusOfLastDownloadAttempt = response.getStatusLine().getStatusCode();
LOG.info("HTTP GET request status: " + this.httpStatusOfLastDownloadAttempt);
LOG.info("Downloading file: " + downloadedFile.getName());
FileUtils.copyInputStreamToFile(response.getEntity().getContent(), downloadedFile);
response.getEntity().getContent().close();
String downloadedFileAbsolutePath = downloadedFile.getAbsolutePath();
LOG.info("File downloaded to '" + downloadedFileAbsolutePath + "'");
return downloadedFileAbsolutePath;
}
}
String s = driver.findElement(By.cssSelector("#navbtm img")).getAttribute("src");
URL url = new URL(s);
System.out.println(url);
BufferedImage bufImgOne = ImageIO.read(url);
ImageIO.write(bufImgOne, "png", new File("test.png"));
I have found an excellent article about it. Tried, and works perfectly:
http://ardesco.lazerycode.com/index.php/2012/07/how-to-download-files-with-selenium-and-why-you-shouldnt/
UPDATE:
Better solution is to get the image from the browser itself:
https://groups.google.com/forum/#!msg/selenium-users/8atiPIh39OY/Gp9_KEXnpRUJ
I have been given a wsdl for a SOAP webservice I need to consume. I have used the wsdl to create webservice classes in netbeans.
The SOAP Header requires a ServiceAuthHeader with username and password.
NetBeans did generate a ServiceAuthHeader class, but I do not know how I can add it to the SOAP Message that gets sent using the classes generated.
I know how to do it at a lower level, i.e. create a SOAPMEssage, add the header, connect to the service and send it, but I have never used jws before, where the nitty gritty bits are done for you, and I am struggling to find out where I add it in any documentation or tutorials.
The ServiceAuthHeader generated is this:
package com.theservice.webservice;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAnyAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.namespace.QName;
/**
* <p>Java class for ServiceAuthHeader complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="ServiceAuthHeader">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="Username" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* <element name="Password" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* </sequence>
* <anyAttribute/>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "ServiceAuthHeader", propOrder = {
"username",
"password"
})
public class ServiceAuthHeader {
#XmlElement(name = "Username")
protected String username;
#XmlElement(name = "Password")
protected String password;
#XmlAnyAttribute
private Map<QName, String> otherAttributes = new HashMap<QName, String>();
/**
* Gets the value of the username property.
*
* #return
* possible object is
* {#link String }
*
*/
public String getUsername() {
return username;
}
/**
* Sets the value of the username property.
*
* #param value
* allowed object is
* {#link String }
*
*/
public void setUsername(String value) {
this.username = value;
}
/**
* Gets the value of the password property.
*
* #return
* possible object is
* {#link String }
*
*/
public String getPassword() {
return password;
}
/**
* Sets the value of the password property.
*
* #param value
* allowed object is
* {#link String }
*
*/
public void setPassword(String value) {
this.password = value;
}
/**
* Gets a map that contains attributes that aren't bound to any typed property on this class.
*
* <p>
* the map is keyed by the name of the attribute and
* the value is the string value of the attribute.
*
* the map returned by this method is live, and you can add new attribute
* by updating the map directly. Because of this design, there's no setter.
*
*
* #return
* always non-null
*/
public Map<QName, String> getOtherAttributes() {
return otherAttributes;
}
}
So I can succcesfully call the service using this:
private static PriceDetailRetunValue priceDetail(PriceDetailInputValue inputValue) {
com.theservice.webservice.WebService service = new com.theservice.webservice.WebService();
com.theservice.webservice.WebServiceSoap port = service.getWebServiceSoap12();
return port.priceDetail(inputValue);
}
and I can parse the response, which of course tells me I need to give credentials.
So how I do I get a handle on the actual SOAP Header message to be able to add the ServiceAuthHeader? I have been looking at the methods of the WebService that is created and seen you can get a request context, and I have seen how you can add credentials to the http request headers, but I haven;t been able to find anywhere to add to the SOAPMEssage.
Any help would be appreciated. Thanks.
I found the answer here http://www.javadb.com/using-a-message-handler-to-alter-the-soap-header-in-a-web-service-client
You need to create a handler, then tell your service to use it.
So my original method just has a couple of lines added
private static PriceDetailRetunValue priceDetail(PriceDetailInputValue inputValue) {
com.theservice.webservice.WebService service = new com.theservice.webservice.WebService();
HeaderHandlerResolver handlerResolver = new HeaderHandlerResolver();
service.setHandlerResolver(handlerResolver);
com.theservice.webservice.WebServiceSoap port = service.getWebServiceSoap12();
return port.priceDetail(inputValue);
}
and the HandlerResolver and Handler look like this...
package com.la.feed.xml.theservice;
import java.util.*;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.ws.handler.*;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
public class HeaderHandler implements SOAPHandler<SOAPMessageContext> {
#Override
public boolean handleMessage(SOAPMessageContext smc) {
Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue()) {
try {
SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope();
SOAPHeader header = envelope.addHeader();
SOAPFactory soapFactory = SOAPFactory.newInstance();
Name headerName = soapFactory.createName("ServiceAuthHeader", "", "http://www.interhome.com/webservice");
SOAPHeaderElement headerElement = header.addHeaderElement(headerName);
Name username = soapFactory.createName("Username");
SOAPElement usernameElement = headerElement.addChildElement(username);
usernameElement.addTextNode("GB1009688");
Name password = soapFactory.createName("Password");
SOAPElement passwordElement = headerElement.addChildElement(password);
passwordElement.addTextNode("verbier");
} catch (Exception e) {
}
}
return outboundProperty;
}
#Override
public Set getHeaders() {
return null;
}
#Override
public boolean handleFault(SOAPMessageContext context) {
return true;
}
#Override
public void close(MessageContext context) {
}
}
package com.la.feed.xml.theservice;
import java.util.*;
import javax.xml.ws.handler.*;
public class HeaderHandlerResolver implements HandlerResolver {
#Override
public List<Handler> getHandlerChain(PortInfo portInfo) {
List<Handler> handlerChain = new ArrayList<Handler>();
HeaderHandler hh = new HeaderHandler();
handlerChain.add(hh);
return handlerChain;
}
}
It needs to be finessed a little, but it does the job.