After authenticating a user using CXF WSAuthentication Interceptor... I need the username in the service implementation (Business Logic). Wondering if there is a easy way to get access to the Username in the Implementation class?
declare these in your implementation class:
#Resource
private WebServiceContext wsContext;
then in any method do:
Principal p = wsContext.getUserPrinciple();
String username = p.getName();
#Resource instructs the web service stack to inject the web service context into your wsContext attribute.
Why not create a user object and place it somewhere in the memory (in a static Map or List etc) with the userName in the wsse:security while while doing the authentication itself? Once you reach the Service endpoint implementation class, you loose the MessageContext and hence its difficult to read the headers.
Related
I have an EJB application that consists of two beans, ServiceEJB (web tier) and BusinessEJB (business tier), where BusinessEJBis injected in ServiceEJB.
ServiceEJBreceives HTTP requests from the browser, calls a method in BusinessEJB, gets the result, and sends the HTTP response.
Also, ServiceEJB has access to the HttpSession object, where the userId of the user that logged in is stored. BusinessEJBdoes NOT have access to the HttpSession object.
The application needs to log messages (using sl4j/logback, for example). It could log the message in ServiceEJBor BusinessEJB methods, and when it logs a message, it has to include the userId of the session in the log entry.
Since BusinessEJB doesn't have the userId, it needs to get it from ServiceEJB. The question is what is the best way to achieve that. What I DON'T want to do is to add a userId field to each method in BusinessEJB as a parameter, as there are many ServiceEJBs and BusinessEJBs in the application (and other beans called by BusinessEJB that also generate log entries), and I don't want to pollute the application with the userId field. Instead, I could have a userId field at the EJB level, but how to populate them? Is there a way to achieve this with annotations? Any suggestions will be welcome.
#Produces({MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_JSON})
#Stateless
public class ServiceEJB {
#Context
HttpServletRequest httpRequest;
#Inject
private BusinessEJB bean;
private String userId;
#Path("someurl")
public Response someMethod1() {
final HttpSession session = httpRequest.getSession();
// get the userId from the session
String s = bean.someMethod2();
// return Response
}
}
#Stateless
public class BusinessEJB {
private String userId;
public String someMethod2() {
// .... log an entry with userId
return "something";
}
}
A few pointers/comments:
If you integrate with application server security, then the user name is available at any component. EJBs can get it by calling getCallerPrincipal() on the injected variant of the EJBContext, here the javax.ejb.SessionContext:
#Resource
private SessionContext sessionCtx;
Servlets can retrieve the principal from the HttpServletRequest.getUserPrincipal(). JAX-RS components (the ServiceEJB) can retrieve it from the javax.ws.rs.core.SecurityContext.getUserPrincipal().
Is there any reason why you are NOT integrating with the application server security?
If you have a good reason NOT to integrate with application server security, I would propose a variation of the solution from the previous answer. The variation is to set the user data from a filter applied to all resources (either servlet filter or JAX-RS ContainerRequestFilter), so that you do not have to worry about setting it in multiple places.
If you ONLY NEED THE USER ID FOR LOGGING, I'd suggest you take a look at the concept of Mapped Diagnostic Contexts (MDC) in slf4j. With it you can set the user id early at the beginning of the request and make it available to all logging statements thereafter.
Create a request scoped CDI bean i.e. UserContext.
Inject it into both EJBs.
In ServiceEJB set user's id and in BusinessEJB read it.
Using Jersey 2.x how would I inject HttpRequest and HttpSession objects? And how to use injected request and Httpsession object in a service class?
in jersey 2.x injected request and session objects in Resource class working fine getting request and session objects
out side like business class not working.
You can try adding #Context HttpServletRequest request to your resources method signature. That will make request available for the duration of the method.
It's not good practice to pass HttpServeltRequest / Session objects down to service or business classes. If you do this, you make it very difficult to use the service class in anything but a Web Application. You should pull the data that the service class requires out of the HttpServletRequest / Session in the Resource class and pass it to service class
For example, if your service class needs access to the userName that is held in an HttpServletRequests "userName" parameter, then the Resource class should do
String userName = req.getParameter("UserName");
serviceClass.doSomething(userName);
rather than
serviceClass.doSomething(req);
A HTML5 UI is connected to the backend (REST Jersey to business logic to Hibernate and DB).
I need to create and maintain a session for each user login until the user logs out.
Can you please guide me on what technologies/ APIs can be used.
Does something need to be handled at the REST Client end also..
Using JAX-RS for RESTful web services is fairly straightforward. Here are the basics. You usually define one or more service classes/interfaces that define your REST operations via JAX-RS annotations, like this one:
#Path("/user")
public class UserService {
// ...
}
You can have your objects automagically injected in your methods via these annotations:
// Note: you could even inject this as a method parameter
#Context private HttpServletRequest request;
#POST
#Path("/authenticate")
public String authenticate(#FormParam("username") String username,
#FormParam("password") String password) {
// Implementation of your authentication logic
if (authenticate(username, password)) {
request.getSession(true);
// Set the session attributes as you wish
}
}
HTTP Sessions are accessible from the HTTP Request object via getSession() and getSession(boolean) as usual. Other useful annotations are #RequestParam, #CookieParam or even #MatrixParam among many others.
For further info you may want to read the RESTEasy User Guide or the Jersey User Guide since both are excellent resources.
Is there a way to pass URL parameters to an authentication provider in Spring Security 3?
Our login page will need to receive an email token as a parameter that the authentication system will need to be aware of when it sets the status of the user. Specifically, it will let a user with a correct token log in that would not otherwise be able to.
I have a custom class extending the DaoAuthenticationProvider class. My authentication logic is in that class's authenticate method.
I'm hoping there is some way to pass this data into the authenticate method.
You could inject the HttpServletRequest object on your authentication provider class:
private #Autowired HttpServletRequest request;
Now, you should be able to access the request parameters with APIs such as request.getParameterValues(paramName)
You need to override UsernamePasswordAuthenticationFilter.setDetails() and pass extra information to your custom authentication provider via details property of UsernamePasswordAuthenticationToken.
I have small application using JSF 1.1. It is using NTLM for authentication.
What is the best approach to store the logged in user_id, so that could be used in application across all java classes, user_id would be used in almost all jsf pages corresponding java classes.
Any help is highly appreciable.
Thanks
store it in the web session :
session=FacesContext.getExternalContext().getSession();
session.setAttribute("user_id",user_id);
This would depend on how you are performing authentication. If you are delegating the authentication process to the container, by using FORM, BASIC or DIGEST authentication, then you can obtain the Principal object associated with the current request using the following snippet:
Principal user = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
The name of the user in the realm can be obtained using the user.getName() method. Under the hood, the container stores the Principal object in the HttpSession instance, but this is not accessible as an attribute using the HttpSession.getAttribute(...) method, in most containers.
The Principal object is also automatically propagated by the Servlet container to the EJB container, when the business method of an EJB is invoked, and you can access it using the SessionContext interface. In an EJB, you can perform the following, to obtain a reference to the Principal:
#Resource
private SessionContext ctx;
public void businessMethod()
{
Principal user = ctx.getCallerPrincipal();
...
}
If you are not delegating authentication to the container, and instead, you are performing authentication using your own scheme, then you must store the reference to the identity of the user in the HttpSession object upon successful authentication, and you must clear this upon session invalidation. Storing it in other scopes is not recommended, as only a HttpSession object has the same lifetime as a user's session with the application.