Can Apache restrict access based on a Tomcat webapp's Spring SecurityContext? - java

We have a tomcat webapp which provides webservices which are protected using Spring Security. The client makes a call to a specific authenticationService method which we wrote to authenticate them and create an authToken which is then used to register them with Spring Security as so:
SecurityContextHolder.getContext().setAuthentication( authToken )
That's all fine and good. However, we also have the requirement that authenticated users be able to access static content which is served by Apache (httpd) on the same server. Is there a way to enforce the requirement that the user has been authenticated (by Java/Spring) before they can download the static content? It seems like Apache and Tomcat would have to somehow share the SecurityContext.
OR - alternatively it seems like Tomcat could serve the static content itself since it already has access to the SecurityContext. If that is the best solution, could anyone provide a pointer to how we would get tomcat to do that (serve static content after checking that the user has been authenticated).
Thanks.

Yes, Tomcat is going to have to serve the static content.
mvc:resources can be helpful here. After that is set up protect those mappings using the standard intercept-url configuration.

Related

Tomcat web.xml: restrict access to specific methods of a servlet

I'm running a web application under Tomcat server. Different servlets are configured using Tomcat's web.xml.
I'm looking for a convenient way to restrict access to specific METHODS of specific URLS so that only these METHODS can be accessed using an Authorization header while others can be accessed without any restriction.
For instance, for url http://localhost:8080/my/servlet1 - GET and OPTIONS can be accessed by any user, while POST and PUT must be authorized with a username and a password, but for url http://localhost:8080/my/servlet2- all methods are open.
How can I implement that?
Thanks
The most low level API that allows you to do all sorts of filtering based on the context of the HTTP request in the javax/servlet/Filter
You implement a filter class that can restrict on the basis of HTTP method and any other criteria you choose. You register the filter on your web.xml and you add rules for which paths it is filtering.
Here is an walk through on applying such a filter.
If you happen to be using more than just a naked Tomcat for your application and you are using Spring Boot on top of it you could use their flavor of filters. This is an example for that case.

Using BASIC Authentication without a Deployment Descriptor

Is it possible to use BASIC authentication without a deployment descriptor (web.xml)?
I have constructed my server using the #WebServlet annotation and have used #ServletSecurity in order to change the accessibility of my servlets, but I want one of my servlets to only be accessible using a username-password combination. I looked over the internet and all I have seen is using web.xml, is there a way to do it without web.xml, but rather with an annotation, or something of the sort? I am using Tomcat 8.5.9 with Gradle and IntelliJ.
Thanks.
I have used (#HeaderParam("Authorization") String authorization) annotation to read the basic auth credentials and used BASE64Decoder to get the username and password for validation.
https://www.java2novice.com/restful-web-services/http-basic-authentication/

Securing a jersey RESTful web service

I'm developing a restful web service that will be consumed by an Android application later on.
Right now, I'm seeking a way to secure the access to my resources:
I found several ways for implementing that on the net, but I can't figure out what is the most appropriate one.
For example, I found that Oauth specifications are more convenient for third-party applications which is not my case.
So what are the most suitable ways for securing jersey APIs, and I'll be glad if someone can provide me with any tutorials/documentations on that.
I'm using a Glassfish v4 server and the Jersey JAX-RS implementation.
After looking at different options I used an authentication filter and basic auth. Very easy to implement.
Some example code:
You need a filter
public class AuthFilter implements ResourceFilter, ContainerRequestFilter {
...
}
And a security context:
public class MySecurityContext implements SecurityContext {
...
}
And a user class:
public class User implements Serializable, Principal {
...
}
Finally, you can add the filters you need like so: (pass your ResourceConfig object to this function)
private void prepareFilters(ResourceConfig rc) {
rc.getProperties().put("com.sun.jersey.spi.container.ContainerRequestFilters",
getClassListing(new Class[]{
AuthFilter.class
}));
rc.getProperties().put("com.sun.jersey.spi.container.ContainerResponseFilters",
getClassListing(new Class[]{
CORSFilter.class, //You might not need this
GZIPContentEncodingFilter.class //You might not need this
}));
rc.getProperties().put("com.sun.jersey.spi.container.ResourceFilters",
getClassListing(new Class[]{
RolesAllowedResourceFilterFactory.class
}));
}
BTW, you can add #Context SecurityContext securityContext; to your resource class(es) or the individual methods for more fine grained access control. The SecurityContext will be injected into the context of your resource so you can access the User object per request with
With this setup you can annotate your REST methods with #PermitAll, #RolesAllowed, etc which gives you a good level of control over your RESTful interface.
I just finished my stateless (without sessions) user auth and management with Jersey.
Let me know if you want a full example or if you want to give it a try yourself ;)
The simplest way would be using the Java EE build-in Container Managed Security model to secure your rest resources as described in this tutorial. It allows you to configure the security based on users and roles stored in a database or file realm in the web.xml or the the classes themselves.
The disadvantage would be that you must start a session, extract the JSESSIONID and send it in each of your requests so that the server can verify it, but that makes your services more 'stateful' and violates the statelessness of the rest architecture.
Another way would be implementing custom security by using WebFilters, like sending the user name and password with each of your requests and verity them based on the information in a special db. If the information doesn't match the information stored in the database a redirect or a special error code can be returend in the Response object.
The best approach I think is using OAuth2 as described in this specification. Dependend on what kind of client you are using (desktop, web page, mobile client) there are different workflows and apart from that lots of benefits like creating tokens for special scopes of your application (read-only or full access,...). Google provides many different apis that can be accessed by the same account. If an applications only needs data from the calendar api, the requested token only gives you access to this special api and not to the entire resources of the account (like mail data, notes, etc). Another point would be that the security handling is decoupled from the client and no password must be stored in the client application.
You can either implement everything on your own or use a open source project like this. It provides a description on how it works and the code is very good but it has many dependencies to spring frameworks. For my use case I've startend replacing them by vanilla Java EE 7 code and create a solution based on the idea of this open source project. The reason behind the replacements was that it's more future-proof and it avoids class loader problems during the deployment.
In the Android app a Authenticator can be implemented for secure storing of the token.

how to check if a user is logged in from another webapp using spring security

i have the following setup.
server1: i am using spring security v3.1.4 in one application. this application is running on its own server (e.g. tomcat at server1.mydomain.com).
server2: i have another 3rd party web application running on a different server (e.g. tomcat at server2.mydomain.com). this applicaton is pluggable in that it allows me to install jars to dynamically modify behavior at runtime. its purpose is to serve content.
users and resource access are managed on server1. content is delivered by server2. on server2, if a resource request comes in, i need to ask server1 if the user is logged in. is this possible to do with spring security? i imagine i would pass in the username with the resource request (e.g. http://server2.mydomain.com?getFileId=1&username=johndoe#gmail.com).
i read a little bit on the spring security website and SSO seems to be the way to go (e.g. using Central Authentication Service). but that seems like an overkill. our architecture already has several servers running.
integration (e.g. the webapp using spring security)
media (e.g. the 3rd party webapp)
elastic search (a cluster)
mysql (a cluster)
if possible we would like to have a minimalist system (but our system isn't small, given our investments and assumptions using rdbms/IR clusters).
any help is appreciated.
One possible way of achieving this - although it's not something I've tried myself - could be to expose Spring Security's SessionRegistry in server1 via a simple REST based controller. That would then allow server2 to remotely query authenticated users in server1 by making a simple HTTP GET request.
It's probably worth having a read of the Session Management section of the Spring Security docs to determine how to access the SessionRegistry. The basic setup I think is to specify a <session-management> tag inside the <http> section of your config on server1.
<security:session-management>
<security:concurrency-control session-registry-ref="sessionRegistry"/>
</security:session-management>
<bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>
You would also need to add a listener to the web.xml of server1
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
The controller that you would need to create on server1 could then be autowired with the SessionRegistry
#Autowired
private SessionRegistry sessionRegistry
From there, you can use sessionRegistry.getAllSessions() to determine whether a username (principal) passed in a request to the controller is logged in on server1.
More of an idea than a concrete answer - but may give you an avenue to explore.

Websphere - What is the best way to hide wsdl's from end user?

I think there are several ways to hide wsdl's from end users for WebSphere (6.1). We use axis to publish Web Services and I currently updated the custom Servlet class (which extends AxisServlet) and override the service method to throw 404 error for urls like: http://xxxx/services/MyService?wsdl. The other option may be adding filters.
Are there any other alternative ways?
Thanks.
What lutz pointed to is correct. You should add some authentication mechanism to your SOAP interfaces if they can do something potentially harmful. However if you insist you can block the access to anything that looks like wsdl query, for instance with
Servlet Filter for your applications
Front-end web server configuration that will redirect those queries to somewhere else, ie.
RewriteEngine On
RewriteRule ^(.+)?wsdl$ /error.html

Categories