how to pass parameter - java

I have written a method for user authentication method in REST web service. After successful authentication, I want to pass the username. How can I pass it? Can I get value pass from login web service method in other web service method.
My code for login is:
#GET
#Produces("application/json")
public Response login(#Context HttpServletRequest req,#Context HttpServletResponse res,#QueryParam("loginname")String loginname,#QueryParam("password")String password) throws IOException, ServletException
{
userDAOImpl impl = new userDAOImpl();
Mongo mongo=impl.getConnection("127.0.0.1","27017");
DB db=impl.getDataBase(mongo,"userdb");
DBCollection coll=impl.getColl(db,"userdb");
userDTO dto = new userDTO();
dto.setUsername(loginname);
dto.setPassword(password);
if(impl.checkUser(coll, dto))
{
mongo.close();
return Response.ok().build();
}
else
{
return Response.status(Response.Status.FORBIDDEN).build();
}
}

I can't tell if you are using some sort of web framework here or not, so I'll answer the question as if you aren't.
Servlets do allow you to add attributes to a request (which are gone after the request is processed), to a page (again, lost when the page is gone), or session (which lives as long as your browser/servlet maintain the session).
I'd suggest you start here with a simple example of how to deal with servlet attributes and paramters. And here's a more detailed explaination.

Related

Is ServletRequest::setAttribute safe in terms of web service security?

Short Version
Is javax.servlet.ServletRequest's method setAttribute(<key>, <Object>) only used as a means of passing objects between methods in Java code?
Long version
Let's say I have a javax.servlet.Filter implementation to handle all logged in users' authentication using cookies:
in Spring Boot
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class AuthFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
Cookie[] cookies = null;
if (request instanceof HttpServletRequest) {
cookies = ((HttpServletRequest) request).getCookies();
}
Optional<User> user = mySessionAuthMethod(cookies);
if (user.isPresent()) {
request.setAttribute("user", user.get());
}
chain.doFilter(request, response);
}
}
Then later, I can avoid manual authentication in all of the Web API methods, and just check the user attribute. Example of a #RestController's method:
#RequestMapping(value = "/profile")
#CrossOrigin(origins = {MyProperties.ORIGIN}, allowCredentials = "true")
public ResponseEntity getProfile(HttpServletRequest request, HttpServletResponse response) {
String user = request.getAttribute("user");
if (user != null) {
return myGetProfileResponse(user);
}
return myNotLoggedInResponse();
}
My questions are:
Is this form of authentication secure? What I mean is, are the attributes in the ServletRequest only added and used in Java for communication between methods, or could they be added to the request already before reaching the server?
Is this way of authentication using Filters a good practice to avoid duplicate code?
Additional Explanation
The real reason of doing this is not only authentication. I have also Filters which need to process each and every request and pass objects to the Controllers. What I definitely want is that none of these objects and information can be forged even by a person who knows the implementation of the system.
I think I have found the answer from the documentation of getAttribute
Attributes can be set two ways. The servlet container may set attributes to make available custom information about a request. For example, for requests made using HTTPS, the attribute javax.servlet.request.X509Certificate can be used to retrieve information on the certificate of the client. Attributes can also be set programatically using ServletRequest#setAttribute. This allows information to be embedded into a request before a RequestDispatcher call.
So according to this (if there is no missing information), it should be completely safe to pass custom objects and know that they were always created by the server.

How to approach this authentication mechanism in Jersey

I am new to Jersey REST Framework , so please excuse if this is a dumb question .
I am using Tomcat with Hibernate and Jersey REST Webservices.
I have got set of HTML pages in my Web APP
login.html
dealer.html
sales.html
I dont want the User to access the HTML pages directly other than login.html
So to resolve this issue , when submit is pressed , under login.html call
following call is made to the backend
#Path("/webchecklogin")
public class WebLoginCheck {
#Context
private HttpServletResponse response;
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces("application/json")
public String getData(LoginInfo loginInfo ) throws JSONException,ClassNotFoundException, SQLException
{
String ID = loginInfo.getID();
String email = loginInfo.getEmail();
// validate this values with Database and if successfully logged in , stored them in session AND cookies also
}
}
And inside dealer.html and sales.html , on page ready i am calling a service as shown below
var checkcallajax = $.ajax({
type: 'GET',
url: url + '/ORIENT/orn/checkifuserloggedin',
jsonpCallback: 'jsonCallback',
success: function(response) {
}
})
#Path("/checkifuserloggedin")
public class CheckIfUserLoggedIn {
#Context
private HttpServletRequest request;
#GET
#Consumes(MediaType.APPLICATION_JSON)
#Produces("application/json")
public String checkIfUserLoggedIn() throws JSONException,ClassNotFoundException, SQLException
{
// On what basis , should i check wheher the USER is logged or NOT
// I tried storing data with Session and cookies , but i am unable to retrive them here
//return true or false
// based on true or false , i am redireting user to appropiate page
}
}
Could anybody please let me know how to approach this
RestFUL web services are supposed to be stateless, so in theory, you could send the credential with every request, and that would be totally stateless from the "server point of view"
Most will find this cumbersome, resource intensive, and storing credentials on the client is somewhat bad from a security point.
The alternative approach could be that your login method returns a token, that needs to be re-sent (in a header maybe) to the server with every request.
The client must know how to store it (session cookie? on the domain
serving html, if you are in a CORS scenario)
The server must know how to validate the token.
On top of it, the validation of the Token can be done in a JaxRS Filter... before reaching your service entry point. And even better, this filter could add roles to the request context, so you can the use the #RolesAllowed annotation with your services.
I "very personnally" avoid relying on the javax.servlet.Session, as this is fundamentally stateful. But, you should be able to do it, given that the clients stores the jSessionId (other other cookie name) in a session cookie. If it does not work, you might have CORS or other domain specific problem, preventing the client from storing and returning this cookie automatically.
Hope it helps.

Is calling request.getSession(true) explicitly required to persist programmatic authentication via request.login(username,password)?

While working on a Java Servlet Filter to integrate with an internal SSO I struggled to find the correct way to create a persistent login using programmatic security functions. Specifically, after reading many tutorials such as this I was calling request.login(username,password) and a user Principal was created that returned correct values for methods request.isUserInRole(role) etc. for the current request.
I expected this to be persistent for the user, but subsequent requests would return null for request.getUserPrincipal() so my authentication code was entered on every request. What I found here after much searching was that calling request.getSession(true) before calling request.login(username,password) causes the Principal to be persistent for the user session.
Is it required to explicitly create a session before logging the user in to persist the Principal for the session? This behaviour seems odd to me so I am wondering if I am doing something wrong. I appreciate any insight from developers more knowledgeable on the matter than myself. Using JDK 7 and Tomcat 8. Realm is an extension of RealmBase that overrides authenticate(username,password), getName(), getPassword(username) and getPrincipal(username).
public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
if(request.getUserPrincipal() == null) {
try {
String userName = request.getParameter(userNameField);
String password = request.getParameter(passwordField);
request.getSession(true); // <-- block always entered without this
request.login(username,password);
}
catch(ServletException e) {
// Handle failed login...
return;
}
}
fc.doFilter(req,res);
}
The answer is in the Tomcat source for AuthenticatorBase.java where the login(username,password) chaining calls the configured Realm's authenticate(username,password) method and then calls register(...) passing the returned Principal and stores it in a session if one exists.

Access PortletSession attributes (set by interceptor) from the controller (Spring Portlet MVC)

I'm new to Spring Portlet MVC, but I've been studying hard on it in the last few days.
The context of my problem is the following
I have a Spring Portlet MVC portlet with a single controller.
The portlet is configured to call an HandlerInterceptor (method 'preHandleRender') anytime a user wants to access to a resource.
The interceptor checks if the user is authenticated, if not, it retrieves the user's Liferay credentials to manage authentication on a number of other webservices (not interesting right now).
After this, the interceptor stores the user data inside the PortletSession.
Now, how am I supposed to retrieve the user data stored in the PortletSession by the interceptor from inside the controller??
sessionInterceptor.preHandleRender
#Override
public boolean preHandleRender(RenderRequest request, RenderResponse response, Object handler) throws Exception {
PortletSession session = request.getPortletSession(true);
.
.
.
session.setAttribute("userProfile", userProfileDomain,PortletSession.APPLICATION_SCOPE);
.
.
.
return true;
}
ViewController class
#Controller("viewController")
#RequestMapping(value = "view")
public class ViewController {
//#Autowired
private WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
#RenderMapping
public String setModelAndView(RenderRequest request, ModelMap tgtModel) {
logger.debug("<< | >> Starting.");
PortletConfiguration conf = PortletConfiguration.getInstance();
.
.
}
}
I am ready to give further information about my code if requested.
I was able to solve the problem and to identify my error.
In the interceptor, as I showed in my question, I set the session attribute "userProfile" in the PortletSession.APPLICATION_SCOPE.
session.setAttribute("userProfile", userProfileDomain,PortletSession.APPLICATION_SCOPE);
As for the controller, I understood you have multiple options:
Pass the request (RenderRequest, in my case) as a parameter, the obtain the session (PortletSession, in my case) from the request and then retrieve the attribute from the session.
Pass directly the session as a parameter and then retrieve the attribute from it.
However, whether you take the first or the second road, if you use the following instruction in the controller
session.getAttribute("userProfile");
you wont get anything because the attribute was set in PortletSession.APPLICATION_SCOPE.
The correct instruction is:
session.getAttribute("userProfile",PortletSession.APPLICATION_SCOPE);
Spring MVC wires the PortletSession if you specify it as parameter.
#RenderMapping
public String setModelAndView(RenderRequest request, PortletSession session, ModelMap tgtModel) {
logger.debug("<< | >> Starting.");
PortletConfiguration conf = PortletConfiguration.getInstance();
.
.
}
See http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/portlet.html#portlet-ann-requestmapping-arguments for the supported types.

JAAS, doing login from outside the container

I have an application with JAAS and i need do an external login from the legacy, so i wrote a servlet with this code bellow, it works fine, but when i do another submit the JAAS tries authenticate again and has failure, and the user is redirected to login page.
here is doPost method:
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
NfWebCallbackHandler callbackHandler = new NfWebCallbackHandler(req);
LoginContext loginContext = null;
boolean loginSuccess = true;
try {
loginContext = new LoginContext("MyLoginContext", callbackHandler);
loginContext.login();
} catch (LoginException e) {
loginSuccess = false;
RequestDispatcher dispatcher = req
.getRequestDispatcher("/login.jsf");
dispatcher.forward(req, resp);
e.printStackTrace();
}
if (loginSuccess) {
RequestDispatcher dispatcher = req.getRequestDispatcher(req
.getParameter("targetUrl"));
dispatcher.forward(req, resp);
}
}
any idea is welcome! thanks!
When you use a JAAS Login Module outside the purview of the container (or at least in a mannaer unrecognizable to the container), the container will not be aware of the fact that the Subject and the set of Principals (associated with the subject) are to be stored and managed by the container.
When you use one of the container-managed authentication schemes, the container actually stores the subject in the Session implementation class (at least in Tomcat 6, this is true), in a manner that is completely opaque to the developer; using getAttribute() on the session object will never return the Subject, and neither can use setAttribute() to override the Subject. When needed, the subject is retrieved from this session field and used for various purposes by the container; for instance, when you invoke getUserPrincipal() or getRemoteUser() on the HttpServletRequest object, the Principal associated with the Subject is actually used to return the result.
If you need to get the container to do all this heavy-lifting for you, then you need to use the JAAS Login module in conjunction with a container managed authentication scheme. If you do not want to go this way, then you'll need to "remember" the Subject and the Principals for the duration of the session; not to forget, all of this has to be done in a secure manner.
I forgot to register my solution for this case, i used this class:
org.jboss.web.tomcat.security.login.WebAuthentication
i wrote something like that:
WebAuthentication webAuthentication = new WebAuthentication();
req.getSession().setAttribute("webAuthentication", webAuthentication);
I dont remember where i found this, but was very useful!
Thanx Vineet Reynolds, the only one who tried to help me hehehe

Categories