Is ServletContext for 'localhost/prj' and 'xyz.com/prj' the same? - servlets

According to the following code, internal and external access of a Tomcat project (prj.war), the ServletContext seems to be different. I state this because after a few internal access to the servlet, an external call resets the value and proceeds normally. May I have your opinions ? Thanks.
public void doPost(HttpServletRequest request, HttpServletResponse response) throws Exception {
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
response.setHeader("Connection", "keep-alive");
PrintWriter out = response.getWriter();
//-------------------------------------------------------------------------------------------------------------//
// P A R A M E T E R S //
//-------------------------------------------------------------------------------------------------------------//
String x_value = request.getParameter("value"); if ( x_value == null ) {x_value = "0";}
//-------------------------------------------------------------------------------------------------------------//
String w_value = ( String ) getServletConfig().getServletContext().getAttribute("value");
if ( w_value == null ) {
w_value = "0";
getServletConfig().getServletContext().setAttribute("value", w_value);
out.println("value reset !!!");
}
out.println("current value = " + w_value);
out.println("add value = " + x_value);
out.println("total value = " + ( w_value = String.valueOf(Integer.valueOf(w_value).intValue() + Integer.valueOf(x_value).intValue()) ));
getServletConfig().getServletContext().setAttribute("value", w_value);
out.println("new value set");
}
EDIT :
SERVER.XML
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
</Host>
<!-- ************************ -->
<!-- package.xyz.com -->
<!-- ************************ -->
<Host name="package.xyz.com" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
<Context docBase="package" path=""/>
</Host>
<!-- ************************ -->
<!-- www.package.xyz.com -->
<!-- ************************ -->
<Host name="www.package.xyz.com" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
<Context docBase="package" path=""/>
</Host>
INIT
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
}

Context is the same, no matter which way you are reaching it (internally or externally). As stated in Oracle document:
There is one context per "web application" per Java Virtual Machine. (A "web application" is a collection of servlets and content installed under a specific subset of the server's URL namespace such as /catalog and possibly installed via a .war file.)
Are you sure that your application is not reloaded (like hot deployment on the server)?

Related

Spring MVC - Tomcat GlobalNamingRessource - Datasource NameNotFoundException

I have read many thread about this issue but couldn't manage to fix it yet. I have this error
Caused by: javax.naming.NameNotFoundException: Name [jdbc/dbName] not bound to this context
I have tomcat 8.5 server.xml :
<GlobalNamingResources>
<Resource auth="Container"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
name="UserDatabase"
pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase" />
<Resource auth="Container"
driverClassName="oracle.jdbc.OracleDriver"
maxActive="10"
maxIdle="5"
maxWait="-1"
name="jdbc/dbName"
password="12345"
type="javax.sql.DataSource"
url="jdbc:oracle:thin:#(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 1.2.3.4)(PORT = 1234)) (ADDRESS = (PROTOCOL = TCP)(HOST = 1.2.3.4)(PORT = 1234)) (LOAD_BALANCE = yes)(CONNECT_DATA =(SERVICE_NAME = ABCDEF) (FAILOVER_MODE =(TYPE = SELECT)(METHOD = BASIC))))"
username="abcdef" />
I have main.java.DataConfig class in a first application called "framework" :
#Configuration
#EnableTransactionManagement
#MapperScan("main.java.mapper")
public class DataConfig {
#Autowired
private ResourceLoader resourceLoader;
/**
* dataSource
* #return
*/
#Bean(destroyMethod = "")
public DataSource dataSource() {
JndiDataSourceLookup jndi = new JndiDataSourceLookup();
return jndi.getDataSource("java:comp/env/jdbc/dbName");
}
...
I pack this application as a war and set it as an overlay for another application. Thus, I have in this application a META-INF/context.xml file like this :
<Context>
<ResourceLink global="jdbc/dbName"
type="javax.sql.DataSource"
name="jdbc/dbName" />
</Context>
The application is building fine with Maven and required dependency are well packed in the war, however, the application cannot find the GlobalNamingResource "dbName".
Now if I put the GlobalNamingResource in context.xml in Tomcat the datasource is found and everything works fine.
But I don't want to (and cannot) change the context.xml of the server so I want to fetch the datasource and let it as it is in server.xml. How to succeed to do so?
Thanks for helping.
Try with below setting, It work ok in my current project.
<bean id="dataSource"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/dbName" />
</bean>

Session invalidate not working

< ?xml version="1.0" encoding="UTF-8"?>
< beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
< security:global-method-security secured-annotations="enabled" />
< security:http>
< security:intercept-url pattern="/index*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
< security:intercept-url pattern="/login123" access="ROLE_ADMIN" />
< security:intercept-url pattern="/employee1" access="ROLE_EMPLOYEE"/>
< security:intercept-url pattern="/emppreviewshow" access="ROLE_EMPLOYEE"/>
< security:access-denied-handler error-page="/login"/>
<security:form-login login-page="/login" default-target-url="/index"
authentication-failure-url="/fail2login"
username-parameter="username"
password-parameter="j_password" />
<security:session-management invalid-session-url="/logout" session-fixation-protection="newSession" >
<security:concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</security:session-management>
<security:logout logout-success-url="/logout" delete-cookies="JSESSIONID" invalidate-session="true"/>
</security:http>
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" >
<constructor-arg name="strength" value="255" />
</bean>
<security:authentication-manager>
<security:authentication-provider>
<security:jdbc-user-service data-source-ref="dataSource"
users-by-username-query=
"select username,password, enabled from USER_MASTER where username=?"
authorities-by-username-query=
"select username,USER_ROLE from USER_ROLE where username =? " />
<security:password-encoder ref="passwordEncoder" />
</security:authentication-provider>
</security:authentication-manager>
when i am clicking the logout and when clicking the back button of browser still it is showing the old pages.I want the same login url to be shown when back button is clicked in browser.
you can check the session is active in your all the methods of the controller classes.ie.,request mapped classes,methods.if the session is active then return the page.otherwise redirect to login page.
Welcome to the world of client vs server! Invalidating a session is an on server operation. Assuming that the session id is passed in a cookie, it means that next request containing that cookie will not be member of the previous session, and so you will activate all the "please login first" machinery.
But under normal conditions, hitting the back button on a browser does not send a new request but just display the last page from the local cache. Thus it is a client only operation.
As an application developper, there is little that you can do. You could try to use javascript to hide back button, catch it, or clean the cache. But if I were you, I won't dare to think about that: you are likely to fall in browser compatibiliy problem, for something that you should not care about. What user reads locally is its own problem. If he/she made a printed copy of a page, you would not take a lighter to burn it when the session is over. The cached pages are the same: a local copy. That's the reason why on explicit disconnection you often see a message asking to close the browser window. Itsi the only way for the user to be sure not to read offline copies if he/she click on the back button.
i cannot use the invalidate-session. i just add the "authentication-success-handler-ref" . and set a session inside there.after login the session is set to true.and after logout the sesison is set to false.
this is the code:
Securuty-context.xml
<bean id="customAuthenticationSuccessHandler" class="org.dewbyte.corebank.utility.CustomAuthenticationSuccessHandler"/>
root-context.xml
<bean id="LogoutSuccessHandler" class="org.dewbyte.corebank.utility.LogoutSuccessHandler" />
CustomAuthenticationSuccessHandler class
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler{
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
#Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
request.getSession().setAttribute("loginStatus", "true");
String targetUrl = "/dashboard";
redirectStrategy.sendRedirect(request, response, targetUrl);
}
public RedirectStrategy getRedirectStrategy() {
return redirectStrategy;
}
public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
this.redirectStrategy = redirectStrategy;
}
}
LogoutSuccessHandler class
public class LogoutSuccessHandler implements org.springframework.security.web.authentication.logout.LogoutSuccessHandler{
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
public RedirectStrategy getRedirectStrategy() {
return redirectStrategy;
}
public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
this.redirectStrategy = redirectStrategy;
}
#Override
public void onLogoutSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
request.getSession().setAttribute("loginStatus", "false");
String targetUrl = "/";
redirectStrategy.sendRedirect(request, response, targetUrl);
}
}
check the session is true or false in every methods in the controller classes.
Controller class
if (request.getSession().getAttribute("loginStatus").equals("true"))
{
return home;
}
else
return login;

Spring security set up access control with oauth2 token

I am discovering oauth2. I have managed to create a sample which return JWToken and REST protected by this token.
Now i would like to improve this by adding access-control in my protected REST interface.
Why ? Because i would like users like ADMIN, READER access some URL or not.
Following http://projects.spring.io/spring-security-oauth/docs/oauth2.html
it is possible over expression-handler in http node.
Here is the configuration i have added to my xml config :
<sec:global-method-security
pre-post-annotations="enabled" />
<sec:http pattern="/protected/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint">
<sec:anonymous enabled="false" />
<sec:intercept-url pattern="/protected/**" />
<sec:custom-filter ref="resourceServerFilter"
before="PRE_AUTH_FILTER" />
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
<sec:expression-handler ref="myexpressionHandler" />
</sec:http>
<bean id="myexpressionHandler" class="org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler">
</bean>
log :
févr. 04, 2015 4:09:31 PM org.springframework.security.config.method.GlobalMethodSecurityBeanDefinitionParser parse
INFOS: Expressions were enabled for method security but no SecurityExpressionHandler was configured. All hasPermision() expressions will evaluate to false.
févr. 04, 2015 4:09:31 PM org.springframework.security.config.http.HttpSecurityBeanDefinitionParser checkFilterChainOrder
But with my JWTtoken I successfully get the protected resource.
My controller:
#Component
#RestController
#RequestMapping(value = "/protected")
public class HelloWorldRest {
private static final Logger LOG = LoggerFactory
.getLogger(HelloWorldRest.class);
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#PreAuthorize("#oauth2.clientHasRole('ROLE_ADMIN')")
#RequestMapping(value = "/greeting/{name}")
public Greeting greeting(#PathVariable String name) {
LOG.info("Fonction greeting : " + name);
return new Greeting(counter.incrementAndGet(), String.format(template,
name + ", I am Mister Toto"));
}
}
I have tested with an user who get authoritiesGrant={ ROLE_NONE }
Thanks,
Any ideas ?
To avoid the error message "SecurityExpressionHandler was configured" you should add the expression handler to your global-method-security. Like this:
<sec:global-method-security pre-post-annotations="enabled">
<sec:expression-handler ref="oauthExpressionHandler" />
</sec:global-method-security>
<oauth:expression-handler id="oauthExpressionHandler" />
Instead of defining your own bean for the WebSecurityExpressionHandler (as you dod in the question) you can additionally use:
<oauth:web-expression-handler id="oauthWebExpressionHandler" />

Block IP Addresses In HttpModule

I have taken over a domain that had was running an old version of Community Server. Needless to say the bots are spamming me trying to find holes.
I'd like to block entire IP blocks before System.Web.HttpRequest.ValidateInputIfRequiredByConfig() is fired. I have a IHttpModule that I have tried but I assume it's getting called after because HealthMonitoring is catching the Exceptions. Here is the module:
public class IpBlockerModule : IHttpModule
{
private static readonly string[] Hacks = new[]
{
"60.169.73.",
"60.169.75.",
"61.160.232.",
"61.160.207.",
"92.85.161."
};
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.BeginRequest += (Application_BeginRequest);
}
private void Application_BeginRequest(object source, EventArgs e)
{
var context = ((HttpApplication) source).Context;
var ipAddress = context.Request.UserHostAddress;
if (!IsHackIpAddress(ipAddress))
{
context.Response.StatusCode = 403; // (Forbidden)
}
}
private static bool IsHackIpAddress(string ip)
{
if (ip == null) return true;
return Hacks.Any(x => x.StartsWith(ip));
}
}
And the relevent web.config sections:
<system.web>
<httpModules>
<add name="IpBlockerModule" type="MyNameSpace.IpBlockerModule" />
</httpModules>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true" >
<add name="IpBlockerModule" type="MyNameSpace.IpBlockerModule" preCondition="" />
</modules>
</system.webServer>
The reasoning behind this is my inbox is getting spammed from all the
A potentially dangerous Request.Path value was detected from the
client
and
A potentially dangerous Request.Form value was detected from the client
notifications. Is something wrong with my Module, or am I correct in assuming modules don't get fired until after the fact?
As an alternative solution have you considered letting IIS do the work for you? This way the request never makes it to your application. You can do this via the web.config and there's an article detailing the process located here. The following example is copied directly from that article and would be placed inside the <system.webServer> section of your web.config:
<security>
<ipSecurity allowUnlisted="true"> <!-- this line allows everybody, except those listed below -->
<clear/> <!-- removes all upstream restrictions -->
<add ipAddress="83.116.19.53"/> <!-- blocks the specific IP of 83.116.19.53 -->
<add ipAddress="83.116.119.0" subnetMask="255.255.255.0"/> <!--blocks network 83.116.119.0 to 83.116.119.255-->
<add ipAddress="83.116.0.0" subnetMask="255.255.0.0"/> <!--blocks network 83.116.0.0 to 83.116.255.255-->
<add ipAddress="83.0.0.0" subnetMask="255.0.0.0"/> <!--blocks entire /8 network of 83.0.0.0 to 83.255.255.255-->
</ipSecurity>
</security>
You can also add the ability to get and log IP addresses so as to identify and block only the spammy ones.
Here's C# code to get IP addresses
string ipadd;
ipadd = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (ipadd == "" || ipaddress == null)
ipadd = Request.ServerVariables["REMOTE_ADDR"];
I noticed that the link in the answer above is dead, so use this well-detailed article here

Basic Auth for WSO2 EI API service

I am using WSO2-EI 6.4.0. I have tried this development with link. It work for me. But I need to get user name and password from other back end service. In this example was showed the hard corded user and password. I have added that code for your reference. Please help me to get those user name and password from property file.
public boolean processSecurity(String credentials) {
String decodedCredentials = new String(new Base64().decode(credentials.getBytes()));
String usernName = decodedCredentials.split(":")[0];
String password = decodedCredentials.split(":")[1];
if ("admin".equals(username) && "admin".equals(password)) {
return true;
} else {
return false;
}
}
I have added WSO2 EI handler like following. I need to pass the value from back service or call other sequence and load.
<api context="/test">
<resource methods="POST">
<inSequence>
................
</inSequence>
<outSequence>
................
</outSequence>
</resource>
<handlers>
<handler class="rezg.ride.common.BasicAuthHandler">
<property name="cm_password" value="admin"/>
<property name="cm_userName" value="admin"/>
</handler>
</handlers>
</api>
When we run the above API, handlers are running first and then running in and out sequences. So I need to get user name and password calling Sequence or any other method before run this BasicAuthHandler.
If you need to read the property file from the class mediator it's just straight forward java property file reading. Please refer the following call sample of reading a property file. In this scenario, Just read the carbon.properties file exists in the conf directory.
public boolean mediate(MessageContext context) {
String passwordFileLocation = System.getProperty("conf.location")+"/carbon.properties";
try (FileInputStream input = new FileInputStream(passwordFileLocation)) {
Properties prop = new Properties();
// load a properties file
prop.load(input);
log.info("------org.wso2.CipherTransformation : " + prop.getProperty("org.wso2.CipherTransformation"));
} catch (IOException ex) {
ex.printStackTrace();
}
return true;
}
To get the server location and the conf locating, There are JAVA system properties are set at the time wso2 server starts. Following are some of the useful System system properties.
carbon.local.ip
carbon.home
conf.location

Resources