annotation based security in tomcat webapp - web-services

I want to achieve webservice security something like this
(http://docs.oracle.com/cd/E24329_01/web.1211/e24983/secure.htm - example is for javaee)
But inside tomcat + jersey application. Is it possible to do so ?
As far as I can see, tomcat does have annotation-api which can work in this case. Unable to figure out how.
package samples.helloworld;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.annotation.Security.RolesAllowed;
#Path("/helloworld")
#RolesAllowed({"ADMIN", "ORG1"})
public class helloWorld {
#GET
#Path("sayHello")
#Produces("text/plain")
#RolesAllows("ADMIN")
public String sayHello() {
return "Hello World!";
}
}

As described in the link above, you should secure your Rest WebServices. Example of Web.xml
<web-app>
<servlet>
<servlet-name>RestServlet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RestServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>Orders</web-resource-name>
<url-pattern>/orders</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>default</realm-name>
</login-config>
<security-role>
<role-name>admin</role-name>
</security-role>
</web-app>

Related

File upload with Jersey using POSTMAN extension : FormDataContentDisposition is NULL

I am getting FormDataContentDisposition object as NULL while implementing jersey file upload example as mentioned in below URL :
http://www.mkyong.com/webservices/jax-rs/file-upload-example-in-jersey/
Here is my sample code,
IMPORTS
import java.io.InputStream;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam;
Rest API code,
#POST
#Path("/uploadFiles")
#Produces({ MediaType.APPLICATION_JSON})
#Consumes({ MediaType.MULTIPART_FORM_DATA })
public Response uploadFiles(#FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("file") FormDataContentDisposition fileDetail)
throws IOException{
I am getting fileDetail object null in above code.
JAR versions used,
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>1.11</version>
</dependency>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-multipart</artifactId>
<version>1.19</version>
</dependency>
I am hitting my request from Chrome POSTMAN Client,
Here is the snapshot of my request from POSTMAN client...
I already gone through the link : File upload with Jersey : FormDataContentDisposition is null having same problem but the difference is that I am using REST Client instead of HTML/JSP to submit my request.
Can any one please help me to know why I am getting NULL object of FormDataContentDisposition,
Thanks in advance!
Edit:
I found the difference between example and my application implementation is that they have below configuration in web.xml
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.mkyong.rest</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
and My Application configuration is,
#javax.ws.rs.ApplicationPath("/rest")
#javax.ws.rs.Path("application")
public class RestServices extends Application {
#Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> classes = new HashSet<Class<?>>();
classes.add(this.getClass());
classes.add(RestAPI.class);
return classes;
}
Can anybody tell me what is the exact difference between these two
configurations. Can Above both implementation will changes the way
things working?
Remove #javax.ws.rs.Path("application").
You don't need two kinds of Deployment Descriptor, use either Programmatic approach or web.xml;
My approach:
empty web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
</web-app>
and config class:
#ApplicationPath("/rootpath")
public class YourApplication extends ResourceConfig {
// Constructor
public YourApplication() {
super (
//YOUR JAX-RS Service Classes
MyJaxRSService.class,
// This one corresponds to jersey-media-json-jackson in dependencies
JacksonFeature.class,
// This is one to : jersey-media-multipart
MultiPartFeature.class
);
}
}
update dependencies
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.22.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.22.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>2.22.1</version>
</dependency>
Last and most important: forget such tutorials, it helps you start instantly but when you encounter problem you're stuck, and you'll just waste your time. Instead read official documentation and their real world examples, get some real insight into technology how and why it works.
Jersey Documentation: https://jersey.java.net/documentation/latest/index.html
In addition: I'd recommend this book by Bill Burke - RESTful Java with JAX-RS 2.0.
Good luck.
Though I am using Jersey 2.22.1, my web.xml has provided configuration for multipart data.
web.xml
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.xyz.rest.controller;com.xyz.rest.filters</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
</web-app>
Reply back if still problem persist

JAX-RS handle multiple authentication mechanism

I'm learning JAX-RS using Jersey and deploy on JBoss EAP 6.3. I'm developing a test application that offers Webservices consumed by different clients. I correctly setted up the basic authentication system based on Roles and username/password (Realm correctly configured and UP&Running). Everything works fine when my client application consume the WS.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>testWS</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Realm</realm-name>
</login-config>
<security-constraint>
<web-resource-collection>
<web-resource-name>Admin Pages</web-resource-name>
<url-pattern>/test/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>role-admin</role-name>
</auth-constraint>
</security-constraint>
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>resteasy.scan.providers</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>resteasy.scan.resources</param-name>
<param-value>false</param-value>
</context-param>
<servlet>
<description>Admin test</description>
<servlet-name>Admin Servlet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.test.webservice.utils.AuthPackageClasses</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Admin Servlet</servlet-name>
<url-pattern>/test/*</url-pattern>
</servlet-mapping>
</web-app>
My second step is to consume the same webservices by a web dashboard which require a login form. My idea is to have a free WS to consume the login and return back some token inside the Cookie in the Response; the same token is stored in my Database.
Other WS must be consumed by the web dashboard injecting the Cookie and the server must validate the token stored in the Cookie.
How can I achieve to authenticate the User coming from two different authentication systems?
Should I redesign my whole authentication system and setup a listener:
if ther's a token in the Cookie -> validate the token
otherwise validate basic authentication
Is there a way to achieve this by configuring the web.xml?
What if I want to implement a third authentication system? My problem is to have the same context-root and validate the caller by different ways.

Spring MVC app with SOAP web service using WSSpringServlet

I have created a simple Spring MVC web application and trying to expose the services as SOAP based JAX-WS services using JAX-WS commons RI implementation.
After deploying my application on Tomcat 7, when I try accessing my web service, I get a message as 404 Not Found: Invalid Request. Below are my configurations, kindly help in resolving this.
web.xml
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes SOAP Web Service requests -->
<servlet>
<servlet-name>jaxws-servlet</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSSpringServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jaxws-servlet</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
WEB-INF/spring/appServlet/servlet-context.xml
<beans:bean id="customerService" class="com.home.service.CustomerService" />
<!-- Web Service definition -->
<beans:bean id="customerWS" class="com.home.ws.CustomerWS">
<beans:property name="customerService" ref="customerService" />
</beans:bean>
<wss:binding url="/ws/CustomerServ">
<wss:service>
<ws:service bean="#customerWS" />
</wss:service>
</wss:binding>
CustomerWS.java
#WebService
#SOAPBinding(style = Style.DOCUMENT, use = Use.LITERAL)
public class CustomerWS {
private CustomerService customerService;
#WebMethod
public Customer read(long id) {
return customerService.read(id);
}
public void setCustomerService(CustomerService customerService) {
this.customerService = customerService;
}
}
CustomerService.java
#Service
public class CustomerService {
public Customer read(long id) {
Customer cust = null;
System.out.println("CustomerService.read invoked");
return cust;
}
}
pom.xml - included the dependency of jaxws-spring
<dependency>
<groupId>org.jvnet.jax-ws-commons.spring</groupId>
<artifactId>jaxws-spring</artifactId>
<version>1.9</version>
</dependency>
There are no errors while building or deploying the application. When I access the URL, still I see no errors in the server log files. However, the browser displays the message - 404 Not Found: Invalid Request
URL I am trying is - http://localhost:8080/crrs/ws/CustomerServ?wsdl
If I access my HomeController, it works fine. Home page is loaded as expected.
Appreciate any help. Thanks in advance.
I'm trying to do the same thing. My code is almost the same, I'm just using #Name and #Inject instead of #Service.
Just added extends SpringBeanAutowiringSupport to the #WebService class and it's working
The servlet mappings in the web.xml seem to be the cause.
<servlet-mapping>
<servlet-name>jaxws-servlet</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
[...]
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
The spring DispatcherServlet named appServlet takes care of all urls after http://localhost:8080/crrs, even http://localhost:8080/crrs/ws/CustomerServ?wsdl.
The WSSpringServlet url-pattern cannot be reached.

Glassfish still use default realm

I have a secure web service (message authentification over ssl) bundeled in a war and I'm trying to use jdbcRealm to authentificate the user.
The jdbcRealm work fine with other ear apps but not for this .war
Actually glassfish is still using the fileRealm despite the configuration done in the web.xml
web.xml:
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<security-constraint>
<web-resource-collection>
<web-resource-name>Secure Area</web-resource-name>
<url-pattern>/xoxoServer/secondWS/*</url-pattern>
<http-method>POST</http-method>
</web-resource-collection>
<!--<auth-constraint>
<role-name>EMPLOYEE</role-name>
</auth-constraint>-->
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>my_realm</realm-name>
</login-config>
</web-app>
In the console I get this :
FIN: [Web-Security] hasResource perm: (javax.security.jacc.WebResourcePermission /secondWS POST)
FIN: JMAC: UnsupportedCallback : javax.security.auth.callback.NameCallback
FIN: JMAC: In PasswordValidationCallback Processor
FIN: jmac login user [test] into realm: file using JAAS module: fileRealm
FIN: Login module initialized: class com.sun.enterprise.security.auth.login.FileLoginModule
FIN: JAAS authentication aborted.
INFO: SEC5046: Audit: Authentication refused for [test].
INFO: SEC1201: Login failed for user: test
How to fix this ?
Thanks.
ps:I'm using Glassfish 3.1.2.2 b5 with jdk6
I solved this by:
packaging the war into an ear
adding the realm in the glassfish-application.xml ( in the ear)

My Rest service won't work in Tomcat and I can't get it to send my resource, what am I doing wrong?

So I started to read this tutorial about how to develop a Restful service with Jersey. I want to develop Rest service that sends the data from a MySQL database to an Android client. I read and followed the steps on the tutorial and made my own resource classes, but when I tried to run the service on Apache I got the following error here.
I'm just starting to experiment with web services and Rest, I have read the information related to the subject from that IBM site and I thought I got the hang of it, but I'm really lost as to why is not working.
My web.xml is as follows
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>TesterRest</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.mx.ipn.escom.testerRest.resources</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
This is my resource class:
package com.mx.ipn.escom.testerRest.resources;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.annotation.XmlRootElement;
import com.mx.ipn.escom.testerRest.dao.TemaDao;
import com.mx.ipn.escom.testerRest.db.Connector;
import com.mx.ipn.escom.testerRest.modelo.Tema;
#XmlRootElement
#Path("/temas")
public class TemaResource {
#Context
UriInfo uriInfo;
#Context
Request request;
#GET
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public List<Tema> getTemas() throws SQLException{
TemaDao temaDao = new TemaDao();
List<Tema> temas=temaDao.getTemas();
temaDao.terminarSesion();
return temas;
}
}
My class for database connection works fine, so that one isn't the problem.
I'm using Eclipse 3.6 to develop and Apache Tomcat 6.
I'm completely new to JAXB, so if anyone can give me guidelines to what kind of annotations am I missing I would appreciate it.
Based on your screenshot I think you should update your web.xml to have the correct package name:
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.mx.ipn.escom.testerRest.resources</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
The mx is missing from your configuration.