Related
How can I prevent XSS attacks in a JSP/Servlet web application?
XSS can be prevented in JSP by using JSTL <c:out> tag or fn:escapeXml() EL function when (re)displaying user-controlled input. This includes request parameters, headers, cookies, URL, body, etc. Anything which you extract from the request object. Also the user-controlled input from previous requests which is stored in a database needs to be escaped during redisplaying.
For example:
<p><c:out value="${bean.userControlledValue}"></p>
<p><input name="foo" value="${fn:escapeXml(param.foo)}"></p>
This will escape characters which may malform the rendered HTML such as <, >, ", ' and & into HTML/XML entities such as <, >, ", ' and &.
Note that you don't need to escape them in the Java (Servlet) code, since they are harmless over there. Some may opt to escape them during request processing (as you do in Servlet or Filter) instead of response processing (as you do in JSP), but this way you may risk that the data unnecessarily get double-escaped (e.g. & becomes & instead of & and ultimately the enduser would see & being presented), or that the DB-stored data becomes unportable (e.g. when exporting data to JSON, CSV, XLS, PDF, etc which doesn't require HTML-escaping at all). You'll also lose social control because you don't know anymore what the user has actually filled in. You'd as being a site admin really like to know which users/IPs are trying to perform XSS, so that you can easily track them and take actions accordingly. Escaping during request processing should only and only be used as latest resort when you really need to fix a train wreck of a badly developed legacy web application in the shortest time as possible. Still, you should ultimately rewrite your JSP files to become XSS-safe.
If you'd like to redisplay user-controlled input as HTML wherein you would like to allow only a specific subset of HTML tags like <b>, <i>, <u>, etc, then you need to sanitize the input by a whitelist. You can use a HTML parser like Jsoup for this. But, much better is to introduce a human friendly markup language such as Markdown (also used here on Stack Overflow). Then you can use a Markdown parser like CommonMark for this. It has also builtin HTML sanitizing capabilities. See also Markdown or HTML.
The only concern in the server side with regard to databases is SQL injection prevention. You need to make sure that you never string-concatenate user-controlled input straight in the SQL or JPQL query and that you're using parameterized queries all the way. In JDBC terms, this means that you should use PreparedStatement instead of Statement. In JPA terms, use Query.
An alternative would be to migrate from JSP/Servlet to Java EE's MVC framework JSF. It has builtin XSS (and CSRF!) prevention over all place. See also CSRF, XSS and SQL Injection attack prevention in JSF.
The how-to-prevent-xss has been asked several times. You will find a lot of information in StackOverflow. Also, OWASP website has an XSS prevention cheat sheet that you should go through.
On the libraries to use, OWASP's ESAPI library has a java flavour. You should try that out. Besides that, every framework that you use has some protection against XSS. Again, OWASP website has information on most popular frameworks, so I would recommend going through their site.
I had great luck with OWASP Anti-Samy and an AspectJ advisor on all my Spring Controllers that blocks XSS from getting in.
public class UserInputSanitizer {
private static Policy policy;
private static AntiSamy antiSamy;
private static AntiSamy getAntiSamy() throws PolicyException {
if (antiSamy == null) {
policy = getPolicy("evocatus-default");
antiSamy = new AntiSamy();
}
return antiSamy;
}
public static String sanitize(String input) {
CleanResults cr;
try {
cr = getAntiSamy().scan(input, policy);
} catch (Exception e) {
throw new RuntimeException(e);
}
return cr.getCleanHTML();
}
private static Policy getPolicy(String name) throws PolicyException {
Policy policy =
Policy.getInstance(Policy.class.getResourceAsStream("/META-INF/antisamy/" + name + ".xml"));
return policy;
}
}
You can get the AspectJ advisor from the this stackoverflow post
I think this is a better approach then c:out particular if you do a lot of javascript.
Managing XSS requires multiple validations, data from the client side.
Input Validations (form validation) on the Server side. There are multiple ways of going about it. You can try JSR 303 bean validation(hibernate validator), or ESAPI Input Validation framework. Though I've not tried it myself (yet), there is an annotation that checks for safe html (#SafeHtml). You could in fact use Hibernate validator with Spring MVC for bean validations -> Ref
Escaping URL requests - For all your HTTP requests, use some sort of XSS filter. I've used the following for our web app and it takes care of cleaning up the HTTP URL request - http://www.servletsuite.com/servlets/xssflt.htm
Escaping data/html returned to the client (look above at #BalusC explanation).
I would suggest regularly testing for vulnerabilities using an automated tool, and fixing whatever it finds. It's a lot easier to suggest a library to help with a specific vulnerability then for all XSS attacks in general.
Skipfish is an open source tool from Google that I've been investigating: it finds quite a lot of stuff, and seems worth using.
There is no easy, out of the box solution against XSS. The OWASP ESAPI API has some support for the escaping that is very usefull, and they have tag libraries.
My approach was to basically to extend the stuts 2 tags in following ways.
Modify s:property tag so it can take extra attributes stating what sort of escaping is required (escapeHtmlAttribute="true" etc.). This involves creating a new Property and PropertyTag classes. The Property class uses OWASP ESAPI api for the escaping.
Change freemarker templates to use the new version of s:property and set the escaping.
If you didn't want to modify the classes in step 1, another approach would be to import the ESAPI tags into the freemarker templates and escape as needed. Then if you need to use a s:property tag in your JSP, wrap it with and ESAPI tag.
I have written a more detailed explanation here.
http://www.nutshellsoftware.org/software/securing-struts-2-using-esapi-part-1-securing-outputs/
I agree escaping inputs is not ideal.
My personal opinion is that you should avoid using JSP/ASP/PHP/etc pages. Instead output to an API similar to SAX (only designed for calling rather than handling). That way there is a single layer that has to create well formed output.
If you want to automatically escape all JSP variables without having to explicitly wrap each variable, you can use an EL resolver as detailed here with full source and an example (JSP 2.0 or newer), and discussed in more detail here:
For example, by using the above mentioned EL resolver, your JSP code will remain like so, but each variable will be automatically escaped by the resolver
...
<c:forEach items="${orders}" var="item">
<p>${item.name}</p>
<p>${item.price}</p>
<p>${item.description}</p>
</c:forEach>
...
If you want to force escaping by default in Spring, you could consider this as well, but it doesn't escape EL expressions, just tag output, I think:
http://forum.springsource.org/showthread.php?61418-Spring-cross-site-scripting&p=205646#post205646
Note: Another approach to EL escaping that uses XSL transformations to preprocess JSP files can be found here:
http://therning.org/niklas/2007/09/preprocessing-jsp-files-to-automatically-escape-el-expressions/
If you want to make sure that your $ operator does not suffer from XSS hack you can implement ServletContextListener and do some checks there.
The complete solution at: http://pukkaone.github.io/2011/01/03/jsp-cross-site-scripting-elresolver.html
#WebListener
public class EscapeXmlELResolverListener implements ServletContextListener {
private static final Logger LOG = LoggerFactory.getLogger(EscapeXmlELResolverListener.class);
#Override
public void contextInitialized(ServletContextEvent event) {
LOG.info("EscapeXmlELResolverListener initialized ...");
JspFactory.getDefaultFactory()
.getJspApplicationContext(event.getServletContext())
.addELResolver(new EscapeXmlELResolver());
}
#Override
public void contextDestroyed(ServletContextEvent event) {
LOG.info("EscapeXmlELResolverListener destroyed");
}
/**
* {#link ELResolver} which escapes XML in String values.
*/
public class EscapeXmlELResolver extends ELResolver {
private ThreadLocal<Boolean> excludeMe = new ThreadLocal<Boolean>() {
#Override
protected Boolean initialValue() {
return Boolean.FALSE;
}
};
#Override
public Object getValue(ELContext context, Object base, Object property) {
try {
if (excludeMe.get()) {
return null;
}
// This resolver is in the original resolver chain. To prevent
// infinite recursion, set a flag to prevent this resolver from
// invoking the original resolver chain again when its turn in the
// chain comes around.
excludeMe.set(Boolean.TRUE);
Object value = context.getELResolver().getValue(
context, base, property);
if (value instanceof String) {
value = StringEscapeUtils.escapeHtml4((String) value);
}
return value;
} finally {
excludeMe.remove();
}
}
#Override
public Class<?> getCommonPropertyType(ELContext context, Object base) {
return null;
}
#Override
public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base){
return null;
}
#Override
public Class<?> getType(ELContext context, Object base, Object property) {
return null;
}
#Override
public boolean isReadOnly(ELContext context, Object base, Object property) {
return true;
}
#Override
public void setValue(ELContext context, Object base, Object property, Object value){
throw new UnsupportedOperationException();
}
}
}
Again: This only guards the $. Please also see other answers.
<%# page import="org.apache.commons.lang.StringEscapeUtils" %>
String str=request.getParameter("urlParam");
String safeOuput = StringEscapeUtils.escapeXml(str);
How can I prevent XSS attacks in a JSP/Servlet web application?
XSS can be prevented in JSP by using JSTL <c:out> tag or fn:escapeXml() EL function when (re)displaying user-controlled input. This includes request parameters, headers, cookies, URL, body, etc. Anything which you extract from the request object. Also the user-controlled input from previous requests which is stored in a database needs to be escaped during redisplaying.
For example:
<p><c:out value="${bean.userControlledValue}"></p>
<p><input name="foo" value="${fn:escapeXml(param.foo)}"></p>
This will escape characters which may malform the rendered HTML such as <, >, ", ' and & into HTML/XML entities such as <, >, ", ' and &.
Note that you don't need to escape them in the Java (Servlet) code, since they are harmless over there. Some may opt to escape them during request processing (as you do in Servlet or Filter) instead of response processing (as you do in JSP), but this way you may risk that the data unnecessarily get double-escaped (e.g. & becomes & instead of & and ultimately the enduser would see & being presented), or that the DB-stored data becomes unportable (e.g. when exporting data to JSON, CSV, XLS, PDF, etc which doesn't require HTML-escaping at all). You'll also lose social control because you don't know anymore what the user has actually filled in. You'd as being a site admin really like to know which users/IPs are trying to perform XSS, so that you can easily track them and take actions accordingly. Escaping during request processing should only and only be used as latest resort when you really need to fix a train wreck of a badly developed legacy web application in the shortest time as possible. Still, you should ultimately rewrite your JSP files to become XSS-safe.
If you'd like to redisplay user-controlled input as HTML wherein you would like to allow only a specific subset of HTML tags like <b>, <i>, <u>, etc, then you need to sanitize the input by a whitelist. You can use a HTML parser like Jsoup for this. But, much better is to introduce a human friendly markup language such as Markdown (also used here on Stack Overflow). Then you can use a Markdown parser like CommonMark for this. It has also builtin HTML sanitizing capabilities. See also Markdown or HTML.
The only concern in the server side with regard to databases is SQL injection prevention. You need to make sure that you never string-concatenate user-controlled input straight in the SQL or JPQL query and that you're using parameterized queries all the way. In JDBC terms, this means that you should use PreparedStatement instead of Statement. In JPA terms, use Query.
An alternative would be to migrate from JSP/Servlet to Java EE's MVC framework JSF. It has builtin XSS (and CSRF!) prevention over all place. See also CSRF, XSS and SQL Injection attack prevention in JSF.
The how-to-prevent-xss has been asked several times. You will find a lot of information in StackOverflow. Also, OWASP website has an XSS prevention cheat sheet that you should go through.
On the libraries to use, OWASP's ESAPI library has a java flavour. You should try that out. Besides that, every framework that you use has some protection against XSS. Again, OWASP website has information on most popular frameworks, so I would recommend going through their site.
I had great luck with OWASP Anti-Samy and an AspectJ advisor on all my Spring Controllers that blocks XSS from getting in.
public class UserInputSanitizer {
private static Policy policy;
private static AntiSamy antiSamy;
private static AntiSamy getAntiSamy() throws PolicyException {
if (antiSamy == null) {
policy = getPolicy("evocatus-default");
antiSamy = new AntiSamy();
}
return antiSamy;
}
public static String sanitize(String input) {
CleanResults cr;
try {
cr = getAntiSamy().scan(input, policy);
} catch (Exception e) {
throw new RuntimeException(e);
}
return cr.getCleanHTML();
}
private static Policy getPolicy(String name) throws PolicyException {
Policy policy =
Policy.getInstance(Policy.class.getResourceAsStream("/META-INF/antisamy/" + name + ".xml"));
return policy;
}
}
You can get the AspectJ advisor from the this stackoverflow post
I think this is a better approach then c:out particular if you do a lot of javascript.
Managing XSS requires multiple validations, data from the client side.
Input Validations (form validation) on the Server side. There are multiple ways of going about it. You can try JSR 303 bean validation(hibernate validator), or ESAPI Input Validation framework. Though I've not tried it myself (yet), there is an annotation that checks for safe html (#SafeHtml). You could in fact use Hibernate validator with Spring MVC for bean validations -> Ref
Escaping URL requests - For all your HTTP requests, use some sort of XSS filter. I've used the following for our web app and it takes care of cleaning up the HTTP URL request - http://www.servletsuite.com/servlets/xssflt.htm
Escaping data/html returned to the client (look above at #BalusC explanation).
I would suggest regularly testing for vulnerabilities using an automated tool, and fixing whatever it finds. It's a lot easier to suggest a library to help with a specific vulnerability then for all XSS attacks in general.
Skipfish is an open source tool from Google that I've been investigating: it finds quite a lot of stuff, and seems worth using.
There is no easy, out of the box solution against XSS. The OWASP ESAPI API has some support for the escaping that is very usefull, and they have tag libraries.
My approach was to basically to extend the stuts 2 tags in following ways.
Modify s:property tag so it can take extra attributes stating what sort of escaping is required (escapeHtmlAttribute="true" etc.). This involves creating a new Property and PropertyTag classes. The Property class uses OWASP ESAPI api for the escaping.
Change freemarker templates to use the new version of s:property and set the escaping.
If you didn't want to modify the classes in step 1, another approach would be to import the ESAPI tags into the freemarker templates and escape as needed. Then if you need to use a s:property tag in your JSP, wrap it with and ESAPI tag.
I have written a more detailed explanation here.
http://www.nutshellsoftware.org/software/securing-struts-2-using-esapi-part-1-securing-outputs/
I agree escaping inputs is not ideal.
My personal opinion is that you should avoid using JSP/ASP/PHP/etc pages. Instead output to an API similar to SAX (only designed for calling rather than handling). That way there is a single layer that has to create well formed output.
If you want to automatically escape all JSP variables without having to explicitly wrap each variable, you can use an EL resolver as detailed here with full source and an example (JSP 2.0 or newer), and discussed in more detail here:
For example, by using the above mentioned EL resolver, your JSP code will remain like so, but each variable will be automatically escaped by the resolver
...
<c:forEach items="${orders}" var="item">
<p>${item.name}</p>
<p>${item.price}</p>
<p>${item.description}</p>
</c:forEach>
...
If you want to force escaping by default in Spring, you could consider this as well, but it doesn't escape EL expressions, just tag output, I think:
http://forum.springsource.org/showthread.php?61418-Spring-cross-site-scripting&p=205646#post205646
Note: Another approach to EL escaping that uses XSL transformations to preprocess JSP files can be found here:
http://therning.org/niklas/2007/09/preprocessing-jsp-files-to-automatically-escape-el-expressions/
If you want to make sure that your $ operator does not suffer from XSS hack you can implement ServletContextListener and do some checks there.
The complete solution at: http://pukkaone.github.io/2011/01/03/jsp-cross-site-scripting-elresolver.html
#WebListener
public class EscapeXmlELResolverListener implements ServletContextListener {
private static final Logger LOG = LoggerFactory.getLogger(EscapeXmlELResolverListener.class);
#Override
public void contextInitialized(ServletContextEvent event) {
LOG.info("EscapeXmlELResolverListener initialized ...");
JspFactory.getDefaultFactory()
.getJspApplicationContext(event.getServletContext())
.addELResolver(new EscapeXmlELResolver());
}
#Override
public void contextDestroyed(ServletContextEvent event) {
LOG.info("EscapeXmlELResolverListener destroyed");
}
/**
* {#link ELResolver} which escapes XML in String values.
*/
public class EscapeXmlELResolver extends ELResolver {
private ThreadLocal<Boolean> excludeMe = new ThreadLocal<Boolean>() {
#Override
protected Boolean initialValue() {
return Boolean.FALSE;
}
};
#Override
public Object getValue(ELContext context, Object base, Object property) {
try {
if (excludeMe.get()) {
return null;
}
// This resolver is in the original resolver chain. To prevent
// infinite recursion, set a flag to prevent this resolver from
// invoking the original resolver chain again when its turn in the
// chain comes around.
excludeMe.set(Boolean.TRUE);
Object value = context.getELResolver().getValue(
context, base, property);
if (value instanceof String) {
value = StringEscapeUtils.escapeHtml4((String) value);
}
return value;
} finally {
excludeMe.remove();
}
}
#Override
public Class<?> getCommonPropertyType(ELContext context, Object base) {
return null;
}
#Override
public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base){
return null;
}
#Override
public Class<?> getType(ELContext context, Object base, Object property) {
return null;
}
#Override
public boolean isReadOnly(ELContext context, Object base, Object property) {
return true;
}
#Override
public void setValue(ELContext context, Object base, Object property, Object value){
throw new UnsupportedOperationException();
}
}
}
Again: This only guards the $. Please also see other answers.
<%# page import="org.apache.commons.lang.StringEscapeUtils" %>
String str=request.getParameter("urlParam");
String safeOuput = StringEscapeUtils.escapeXml(str);
I'm developing an application where I would like to create a compiled and defined custom text-protocol. I.e. I want to send textstrings that represent information / actions to take in a server-client based system.
Is there any reference / best practice way to do this object oriented (in java)?
Some examples of the actual text strings that might be sent, for convenience separated with spaces (will be split by something else in the real case):
command1 <timestamp> <id> <arg1> <arg2>
command2 <timestamp> <id> <arg1> <arg2> <arg3>
command3 subcommand1 <timestamp> <id>
command3 subcommand2 <timestamp> <id>
So some things are included in all messages, but in other ways the messages could be totally different, depending on future implementations and so on.
What I would like to achieve with this is that the received textstring should be parsed with this protocol so that the parties that use it only have to pass the received text string to the protocol and then be able to switch to different functionality depending on the message type. My first thought was if it was possible to implement a base class, let's say "Message", and then subclasses for more specific message types (example Register or UpdateSomething).
Pseudo code to explain roughly what I wanted to achieve:
object msg = new Message(rawText);
switch (msg.getType()) {
case Message.Register:
// Register logic, data needed would be available in the msg-object.
// Most likely a function, for instance: handleRegistration(msg.uid, msg.password)
break;
case Message.SomeData.Get:
// logic/function to return SomeData, args/data needed would be available in the msg-object.
break;
case Message.SomeData.Update:
// logic/function to update SomeData, args/data needed would be available in the msg-object.
break;
default:
// Some default logic.
break;
But I realized that even if I was able to parse the rawText and somehow transform it into different objects depending on its contents (How can I do this?), it wouldn't be possible to switch on object type in a nice way and I've seen that many argue that it isn't a good approach.
I can get all this to work in lots of ugly ways, that's no problem, I'm just very unsure about the correct approach to this. I'd really like to learn how to do this in a nice and usable way also considering scaling (the protocol will grow). I want the protocol to just be a package (jar) that each party (different clients and the server) can use after which no one needs to bother with what (text) is actually sent over the connection.
Any help and guidance is greatly appreciated, I'm open to take other completely different paths. Do note again however that I'm not asking for help to just "get it working". I'm asking about the best practice(s) to implement those things, or references where I and others reading this can learn how to do this.
Thanks!
EDIT:
I guess the main problem I have is the problem itself. The messages differ quite a bit from each other, meaning I will end up in quite a few classes if I want the data members to be unique. This in itself isn't really a problem, it's just the names have to be unique as well. I'd like to group them up in some hierarchy.
For example with the REGISTER type:
A REGISTER message is a type of MESSAGE. But there are also different kinds of register messages:
REGISTER REQUEST <id> <password>
REGISTER OK
REGISTER ERROR <reason>
I would like to group these up in the sense that they are all register messages, but they are also different types of register messages with different payloads (ie need a different set of members if translated to objects). So if I'd like an object to be able to extract this information from variables I'd need 3 classes for this (example RegisterRequestMessage, RegisterOKMessage, RegisterErrorMessage) and it just feels as if all those classes and names could get a bit too much.
I wish to achieve:
Readability and usability for the developer using the protocol, when
they make their switch case to see which message they received or
when they make a new message they should easily (in a IDE that
supports it) be able to list the message-types they can choose from.
Be able to extract information from a message that is unique for
different message-types depending on what is being sent. I'd like the
data available to such a message to be visible (again in a IDE that
supports it) when the object is being used.
I guess there won't be any real smooth way here, either I'll end up with lots of classes (the problem is really lots of long names for messagtypes/classes), or I'll end up having to make it more generic, filling up a json-object or similar with the data.
Lots of classes:
handleRegisterMessage(MyLongNameSpecifiedMessageClass msg) {
this.id = msg.id;
this.password = msg.password;
// etc etc
}
More generic json or such:
handleRegisterMessage(JSONObject msg) {
this.id = msg.get("id");
this.password = msg.get("password");
// etc etc
}
I'm not sure if there's much more to do, but if you guys with more experience see some more elegant or easier solution here that I don't I'm happy to try it out.
EDIT 2:
Decided to use a unique class for each message type, even though there will be quite a few messages and the names might get somewhat long / ugly It felt like the most encapsulated and easy-to-use way. It will be compiled into a jar file and used that way anyways. Thanks for all suggestions though since other people might decide to take other paths.
If I understand what you mean, basically, a message is something that must
be parsed from a string,
be used to do something.
So, you could have something like
abstract class Message {
public abstract void doSomething();
private String myType; // or enum, or whatever
public String getMyType() {
return myType;
}
public static Message parse(String s) {
// parse s
// if s contains command 'register', return a new RegisterMessage
// if s contains command 'someDataGet', return a new SomeDataGetMessage
return // a newly created message;
}
}
class MessageRegister extends Message {
#Override
public void doSomething() {
// do what a Register message does
}
public MessageRegister() {
myType = "REGISTER";
}
}
class MessageSomeDataGet extends Message {
#Override
public void doSomething() {
// do what a SomeDataGet message does
}
public MessageSomeDataGet() {
myType = "SOMEDATAGET";
}
}
Then, you create a new message with
Message m = Message.parse("some command");
You can switch on the message type like this:
switch (m.getMyType()) {
case "SOMEDATAGET":
// whatever
}
The way I usually do this is with an interface, lets call it ConsoleProgram that takes string arguments and a HashMap that couples a string to a Program. Basically doing something similar to your switch statement and then each Program can worry about its own format when its passed the rest of the string (excluding the first program selecting part of the string)
public interface ConsoleProgram {
public String getProgramName(); //what the command string starts with to call this program
public void runProgram(String[] arguments);
}
Then a single class can deal with recieving strings and passing them to ConsolePrograms without ever worrying about what the ConsoleProgram actually does
public class Console{
public static HashMap<String, ConsoleProgram> availablePrograms=new HashMap<>();
public void registerProgram(ConsoleProgram program){
availablePrograms.put(program.getProgramName().toLowerCase(), program);
}
public void recieveCommand(String command){
String[] parts = command.split(" ");
ConsoleProgram program=availablePrograms.get(parts[0].toLowerCase());
if (program!=null){
System.out.println(
program.runProgram(Arrays.copyOfRange(parts, 1, parts.length));
}else{
System.out.println("program unavailable");
System.out.println(
availablePrograms.get("availableprograms").runProgram(parts, this, null)
);
}
}
}
This is something I myself use to support administrative functions within a game I am developing and it scales very nicely. Furthermore if a ConsoleProgram needs access to unusual things you don't need to have Console know about them, the specific ConsoleProgram can take those objects in its constructor before being registered using registerProgram
Instead of writing your own serializers/parcers I recommend using one of well-known tools that are created exactly for that.
One of my favourites is protocol buffers from google and there are many others.
With protocol buffers you would need to define your custom message formats (look at their simple java tutorial for reference), and then generate java code for it.
You would do it on both server/client sides, or, I guess you could simply include generated files along with dependency jar in your library and share it between server/clients.
This will have number of benefits :
You won't need to write your serializer/parser (and more importantly spend time debugging it!)
It is flexible, you can change/extend your messages in future
You are not limited to Java implementations, same message format can be understood by other servers/clients written in C++/Python.
I know this question has been asked quite a few times, however, I have a different approach of what I want to achieve.
Since Play 1.1, you're able to match hosts. This is very useful, however, it means that for every controller, I will need to pass through the subdomain route param. This is quite a burden and repeatful if I have hundreds of controllers which use the subdomain param.
Is there not a way to create a filter which looks at the host name before everything else is executed and then sets an on-the-fly config value for that request?
For example (brainstorming), a filter would do the following:
// use request host, but hard-coded for now...
String host = "test.example.com";
Pattern p = Pattern.compile("^([a-z0-9]+)\\.example\\.com$");
Matcher m = p.matcher(host);
if (m.matches()) {
// OUT: test
System.out.println(m.group(1));
System.setProperty("host", m.group(1));
}
And in the models I'd do something like System.getProperty("host");
I know this isn't how it should be done, but I'm just brainstorming.
At least with this way:
I don't have to pass the subdomain param through to every
controller.
I don't have to pass the subdomain param through to any models
either
Models have direct access to the subdomain value so I can filter out objects that belong to the client
Also, I'm aware that System.setProperty() always applies to the entire JVM; which is a problem. I only want this value to be available throughout the duration of the request. What should I use?
Let's analyse. How would you do it? What would be a good approach? Is this possible with Play? I'm sure there are quite a few running into this problem. Your input is highly appreciated.
I think you are close. If I had to do this, I would write a controller annotated with #Before and have that method extract the hostname from the request headers and put it in renderArgs.
Something like this (I haven't tested it):
public class HostExtractor extends Controller {
#Before
public static void extractHost() {
// Code to read from request headers and extract whatever you need here.
String host = 'Your Code Here'
renderArgs.put("hostname", host);
}
}
Then, in your other controllers, you tell it you want to use that controller above as a filter.
#With(HostExtractor.class)
public class MyController extends Controller {
public static void homepage() {
String hostname = renderArgs.get("host", String.class);
// Do whatever logic you need to render the page here.
}
}
Again, I haven't tested this, but I'm doing something similar to cache objects in memcache. I hope that helps!
It is a common way to decouple text messages and source code in C/Python/PHP/etc by means of gettext set of utilities. I'm trying to do something similar in my Java project, according to this instruction. Is it the best possible way? Or I should try something different and more advanced?
ps. I would like to avoid complex initialization and ideally my Java code should look like:
[...]
public String howBigIsTheFile(File f) {
String name = f.getAbsolutePath();
long length = f.length();
return _("The file %s is %d bytes long", name, length);
}
Something like gettext-commons maybe?
I assume this question is about stand-alone application (command-line, SWING, etc) and not about server-side application (with multiple users accessing concurrently).
In stand-alone application, the easiest is to create a single static accessor class that would be responsible for loading a single resource bundle and then looking up strings in that resource bundle.
Something like this:
public class ResourceUtil {
private static ResourceBundle rb;
static {
//set the default locale
setLocale(Locale.ENGLISH);
}
public static void setLocale(Locale locale) {
rb = ResourceBundle.getBundle("Resources", locale);
}
public static String tr(String key, Object... args) {
return MessageFormat.format(rb.getString(key), args);
}
}
You can change the active locale with setLocale(Locale) method and access translated strings with tr(String,Object...) method.
Then, you could call it from your class like this:
import static ResourceUtil.tr;
public String howBigIsTheFile(File f) {
String name = f.getAbsolutePath();
long length = f.length();
return tr("The file %s is %d bytes long", name, length);
}
Notice the static import.
Disclaimer: all provided code is on pseudo-code level and is not guaranteed to compile.
Depending on the size of your application, you might find it useful to use IDE string externalization support (e.g. see chapter in Eclipse JDT help, I'm sure other IDEs have some similar features).
You could also use several resource bundles and/or several static classes - it depends on the size of your application and your personal preference. See this question for further debate about this.
In a server-environment using static approach like above would lead into issues as different users would have different locales. Depending on your webapp framework, you would solve this issue differently (e.g. use MessageSource in Spring).
If you think about I18N/L10N, Java has its own mechanism here: the properties file. You can see an example in the internationalization tutorials. It's even simpler than gettext stuff :).