I have an application using Jetty 8.1.8 (I can't upgrade it to the most current 9.4 at this time although I did also try the latest 8.1.22) as an embedded server started programmatically. It's been working great for a number of years and we haven't had to change any of it until now, however we now have need of basic user sessions so we're adding that.
Unfortunately, when we try to extract the session to use it in our handlers with HttpSession session = request.getSession(true); we get the following exception:
java.lang.IllegalStateException: No SessionManager
at org.eclipse.jetty.server.Request.getSession(Request.java:1270)
I've dug through all the documentation and many SO posts such as this and this and cannot get this to work without throwing the above exception.
Here is the code we are currently using after many variations attempting to add the sessions.
Server server = new Server(Port);
server.setGracefulShutdown(5000);
server.setStopAtShutdown(true);
HandlerCollection handlers = new HandlerCollection();
// MainHandler inherits from Jetty's AbstractHandler and just contains a couple of additional simple variables that get updated when `handle` is called
MainHandler main = new MainHandler(...);
// *** Session additions begin here
HashSessionIdManager idManager = new HashSessionIdManager();
server.setSessionIdManager(idManager);
HashSessionManager sessionManager = new HashSessionManager();
SessionHandler sessions = new SessionHandler(sessionManager);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
context.setHandler(sessions);
handlers.setHandlers(new Handler[] { main, context });
// *** Session additions end here
server.setHandler(handlers);
//server.setHandler(main); // this is how it was set previously
server.start();
Does anyone have ideas on what might be wrong with this? Hopefully it's something simple that we're overlooking.
Related
I am new to Jetty and working on a test app to do the basic authentication. There is no web.xml in the project. Everything is handled by code.
I followed this example:https://github.com/eclipse/jetty.project/blob/master/examples/embedded/src/main/java/org/eclipse/jetty/embedded/SecuredHelloHandler.java
Here is the test code
Server server = new Server(8080);
LoginService loginService = new HashLoginService("MyRealm", path);
loginService.setRefreshInterval(5);
server.addBean(loginService);
ConstraintSecurityHandler security = new ConstraintSecurityHandler();
server.setHandler(security);
Constraint constraint = new Constraint();
constraint.setName("auth");
constraint.setAuthenticate(true);
constraint.setRoles(new String[] { "user", "admin" });
ConstraintMapping mapping = new ConstraintMapping();
mapping.setPathSpec("/*");
mapping.setConstraint(constraint);
security.setConstraintMappings(Collections.singletonList(mapping));
security.setAuthenticator(new BasicAuthenticator());
security.setLoginService(loginService);
HelloWorld hw = new HelloWorld();
security.setHandler(hw);
server.start();
Here is my test realm.properties
guest:CRYPT:guVeRgi5kAY4k,user,admin
The code is triggered by a test button in a test PDE project. When the server started for the first time, it prompted a window for username/password. I typed "guest" and "guest", and it worked. But after that, when I restarted the server, it never asked for username/password again. The page was loaded without authentication. If I changed password in the realm property file, the prompt will show up again, and still only for that one time. What did I miss? Thanks
Standard HTTP Cookie and Servlet Session behavior is what is going on.
The restart of the server doesn't cause the client provided Cookies to no longer work. You'll want to configure your Cookie and Session behavior to suit your needs (search on SessionCookieConfig and its ilk).
While my application is running, I'm not able to save static assets that are being served. This is kind of a pain for debugging as I'd like to just be able to refresh the page when editing css, js and html.
I thought that the line listener.getFileCache().setEnabled(false); below would do the trick, but it still won't let me edit these files. Is there something else I missed in the configuration?
Here's my application...
final HttpServer server = HttpServer.createSimpleServer(".", 8181);
WebappContext ctx = new WebappContext("Socket", "/");
//enable annotation configuration
ctx.addContextInitParameter("contextClass", "org.springframework.web.context.support.AnnotationConfigWebApplicationContext");
ctx.addContextInitParameter("contextConfigLocation", "com.production");
//allow spring to do all of it's stuff
ctx.addListener("org.springframework.web.context.ContextLoaderListener");
//enable web socket support
final WebSocketAddOn addon = new WebSocketAddOn();
for (NetworkListener listener : server.getListeners()) {
listener.registerAddOn(addon);
//if false, local files (html, etc.) can be modified without restarting the server
listener.getFileCache().setEnabled(false);
}
//add jersey servlet support
//#todo add spring support to jersey
ServletRegistration jerseyServletRegistration = ctx.addServlet("JerseyServlet", new ServletContainer());
jerseyServletRegistration.setInitParameter("com.sun.jersey.config.property.packages", "com.production.resource");
jerseyServletRegistration.setLoadOnStartup(1);
jerseyServletRegistration.addMapping("/api/*");
//add atmosphere servlet support
AtmosphereServlet atmosphereServlet = new AtmosphereServlet();
AtmosphereFramework f = atmosphereServlet.framework();
ReflectorServletProcessor r = new ReflectorServletProcessor();
r.setServletClassName("com.sun.jersey.spi.spring.container.servlet.SpringServlet");
f.addAtmosphereHandler("/socket/*", r);
ServletRegistration atmosphereServletRegistration = ctx.addServlet("AtmosphereServlet", atmosphereServlet);
atmosphereServletRegistration.setInitParameter("org.atmosphere.websocket.messageContentType", "application/json");
atmosphereServletRegistration.setInitParameter("com.sun.jersey.config.property.packages", "com.production.resource");
atmosphereServletRegistration.setInitParameter("com.sun.jersey.api.json.POJOMappingFeature", "true");
//atmosphereServletRegistration.addMapping("/socket/*");
atmosphereServletRegistration.setLoadOnStartup(1);
//serve static assets
StaticHttpHandler staticHttpHandler = new StaticHttpHandler("src/main/web");
server.getServerConfiguration().addHttpHandler(staticHttpHandler, "/");
Update:
I ended up migrating my AngularJS application outside of the java world due to the nature of AngularJS not needing to be a part of the java project.
In order to get the Weblogic initial context to query the task database i am doing the following:
Properties h = new Properties();
h.put(Context.SECURITY_PRINCIPAL, "weblogic");
h.put(Context.PROVIDER_URL, "t3://localhost:17101");
h.put(Context.SECURITY_CREDENTIALS, "weblogic");
h.put(Context.SECURITY_AUTHENTICATION, "simple");
WLInitialContextFactory test = new WLInitialContextFactory();
test.getInitialContext(h);
Context ctx = null;
ctx = getInitialContext();
WorklistContext wliContext = WorklistContextFactory.getRemoteWorklistContext(ctx, "MyTaskApplication");
I then get the TaskQuery interface with the following code:
WorklistTaskQuery taskQuery = wliContext.getInterfaceForTaskQuery();
and to get the tasks i do:
taskQuery.getTasks(query);
where query is com.bea.wli.worklist.api.TaskQuery object.
Please note that this code is running inside the domain running the tasks.
Unfortunally i am getting the following error when i call the getTasks methods:
java.lang.SecurityException: [WLI-Worklist:493103]Access denied to resource /taskplans
/Manual:1.0. Applicable policy: Query Caller: principals=[] Method: com.bea.wli.worklist.security.WorklistSecurityManager.assertTaskAccessAllowed
It seems Weblogic is ignoring the user set on the new initial context and trying to use the one coming from the browser. It so happens that i might need to do query searchs in background workers that don't have a browser session(obviously).
Can anyone help with this?
I've found a solution for this, though it's convoluted and ugly as hell.
Since i'm making these calls through an EJB i can authenticate the call by grabbing the EJB implementation from an authenticated context like so:
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.SECURITY_PRINCIPAL,"user");
env.put(Context.PROVIDER_URL,"t3://localhost:7001");
env.put(Context.SECURITY_CREDENTIALS,"password");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
getSessionInterface(interfaceClass, new InitialContext(env));
Your best bet for this is to avoid the above example and this API all together. Just use the regular MBean Implementation which allows authentication.
Update this solution doesn't seem to be viable, it will screw up the transaction management. Will report back, but it seems if you need to create tasks outside of an authenticated context you will need to go the MBean way
I'm using Jetty 6 as an embedded web server in my Java app. Heretofore, I've had no reason to serve static content, but now I'd like to not only serve static content but also show directory listings.
I've tried using the ResourceHandler class to do this, but at some point mortbay removed the ability for ResourceHandler to do directory listing.
I'd like to do this without adding .jsp or servlet functionality and without web.xml configuration. In short I'm trying to do this programmatically.
For the life of me, I can't find any examples for this online. Could someone point me in the right direction?
Thanks much!
Okay, I figured out how to get Jetty to do what I wanted, which once again was to host some static content in addition to handling some custom servlets.
Ostensibly, the way to do this was to create a DefaultServlet and set the resourceBase and pathSpec accordingly, to allow me to host some directory on /www/*. However, this never worked. In fact, I couldn't find any explanation as to how the pathSpecs actually work or are supposed to be defined.
Thus, I had to create an additional ServletHandler and Context and add both my orginal Context and the new one for static content hosting to the Server.
I did that like so:
Server srv = new Server( port );
// create context and handler for my servlets
Context ctx = new Context();
ServletHandler sh = new ServletHandler();
// ... adding servlets here ...
// create context and handler for static content
ServletHandler sh2 = new ServletHandler();
ServletHolder holder = new ServletHolder( new DefaultServlet() );
holder.setInitParameter("resourceBase", staticResourceBase);
sh2.addServletWithMapping( holder, "/*" );
staticContext.setContextPath(staticPathSpec);
staticContext.setServletHandler(sh2);
// add both contexts to server
ContextHandlerCollection contexts = new ContextHandlerCollection();
contexts.setHandlers(new Handler[] { staticContext, ctx });
srv.setHandler(contexts);
This may not be the preferred way to do this, but it did allow me to add static content hosting to my Jetty-based app programmatically.
If you have a webapp and just jetty running, I think the default is to serve any static content out of the webapp root directory (e.g. the same directory that WEB-INF resides in). So for example you might have the following directories:
mywebapp
- WEB-INF
- static
- site_img.gif
And you can now serve http://mysite.com/static/site_img.gif
Correct me if I'm wrong and I'll remove this answer, this is just off the top of my head.
I'm trying to lookup an EJB from a standalone java application. I'm thinking in terms of WebSphere Application Server 6.1, but if someone knows how to do this for another application server, it may get me in the right direction.
What I'm currently doing:
initialContext= new InitialContext(env);
initialContext.lookup("");
lc = new LoginContext("WSLogin", new WSCallbackHandlerImpl("wasadmin", "defaultWIMFileBasedRealm", "wasadmin"));
lc.login();
subject = lc.getSubject();
WSSubject.setRunAsSubject(subject);
This isn't working... my subject is still "/UNAUTHENTICATED", and I get an error when I try to lookup the EJB. I'm also specifying the following parameters to the VM when executing the application:
-Dcom.ibm.CORBA.ConfigURL="C:\was\profiles\AppSrv01\properties\sas.client.props"
-Djava.security.auth.login.config="C:\was\profiles\AppSrv01\properties\wsjaas_client.conf"
For WebSphere 6, was trying to acceess an secured EJB from a servlet (Jersey-RESTful WAR) also deployed in the same WebSphere; Here is the code that works
Properties prop = new Properties();
prop.put("org.omg.CORBA.ORBClass", "com.ibm.CORBA.iiop.ORB");
prop.put("java.naming.factory.initial", "com.ibm.websphere.naming.WsnInitialContextFactory");
prop.put("java.naming.provider.url", "corbaloc:iiop:localhost:9810");
prop.put("com.ibm.CORBA.securityEnabled", "true");
prop.put("com.ibm.CORBA.validateBasicAuth", "true");
Context ctx;
try {
ctx = new InitialContext(prop);
System.out.println("Resolved Inital Context");
Object ejbHome = ctx.lookup("");
System.out.println("Resolved Home OperationManagerEJB");
logger.info("So far so good, tryining to Login ");
LoginContext lc;
lc = new LoginContext("WSLogin",new WSCallbackHandlerImpl("username","password"));
lc.login();
logger.info("Login Suceeded with omc_user");
WSSubject.setRunAsSubject(lc.getSubject()); //This is one key call
logger.info("Setting the authorization sibject");
References
http://pic.dhe.ibm.com/infocenter/wasinfo/v6r1/index.jsp?topic=%2Fcom.ibm.websphere.express.doc%2Finfo%2Fexp%2Fae%2Frtrb_secprobs.html
http://pic.dhe.ibm.com/infocenter/wasinfo/v6r0/index.jsp?topic=%2Fcom.ibm.websphere.express.doc%2Finfo%2Fexp%2Fae%2Fxsec_jaas.html
http://pic.dhe.ibm.com/infocenter/wasinfo/v6r0/index.jsp?topic=%2Fcom.ibm.websphere.express.doc%2Finfo%2Fexp%2Fae%2Fxsec_jaas.html