Sharing data in spring session attributes - spring-mvc

Am using spring security and spring MVC. Am keeping a data in session attribute in unAuthenticated request(security:none in spring security). I tried printing the session id.After that i logged into the application. here new session is created. i tried printing the session id. both are different. but when i access the data placed in session attribute. it exist. In my understanding as new session is created after login, data should get lost or Is spring is sharing the session attributes ?
below is the code.
#RequestMapping(value = "/persistFKey")
public #ResponseBody String persistFKey(HttpServletRequest req,HttpServletResponse res,ModelMap modelMap) {
System.out.println("SEssion ID ----persistKey ----"+request.getSession().getId());
String fkey = request.getParameter("fkey");
modelMap.addAttribute("fkey", fkey);
return "success";
}
In spring security xml, i gave
<sec:http security="none" pattern="/portal/persistFKey" />
After login, while invoking the new page am getting the data kept in session attribute
#RequestMapping(value = "/renderScreen")
public String renderScreen(HttpServletRequest request, Model model,
#ModelAttribute("srceenModel") ScreenModel srceenModel,ModelMap modelMap) {
System.out.println("SEssion ID ----renderBooking----"+request.getSession().getId());
System.out.println("SessionKey persisted --------"+(String)modelMap.get("fkey"));
}
Both are in same spring MVC controller.

By default, Spring Security changes the user's session id on login to avoid Session Fixation attacks.
It is also nice enough to migrate the user's old session data to the new one.
You can change this behaviour via <session-management session-fixation-protection="..." />

Related

Session atributes missing from spring session when setting inside HttpSessionListener

In servlet based application I want to make session replication using Spring Session Data Redis. Everything works fine but for csrf security we are using owasp scrfgaurd, where in that flow session token will set at HttpSessionListener.The token is missing while validating.
I tried creating standalone code reproduce the issue.I have created SampleHttpListener and setting some attributes to the session, but these values I am not able to see at servlet level.
Please tell me anything I am missing or any other approach for this senario.
I have added source code here
https://github.com/surya0420/SpringSession
public class CsrfGuardHttpSessionListener implements HttpSessionListener {
#Override
public void sessionCreated(HttpSessionEvent event) {
HttpSession session = event.getSession();
CsrfGuard csrfGuard = CsrfGuard.getInstance();
csrfGuard.updateToken(session);
if(session.getServletContext()!=null){
session.getServletContext().setAttribute(OWASP_CSRFTOKEN,session.getAttribute(OWASP_CSRFTOKEN));
}
}
Since session attributes are missing which are setting at HttpSessionListener level, so I am setting it to
session.getServletContext().setAttribute(OWASP_CSRFTOKEN,session.getAttribute(OWASP_CSRFTOKEN));
after session got created I am setting back the attributes at filter level as shown below at Filter level
if(((HttpServletRequest) request).getSession().getAttribute(OWASP_CSRFTOKEN) == null) {
((HttpServletRequest) request).getSession().setAttribute(OWASP_CSRFTOKEN, request.getServletContext().getAttribute(OWASP_CSRFTOKEN));
}

Access UserDetails object in Websocket session Spring MVC

In a call sent over a websocket connection in a Spring MVC 4 application, I can get a java.security.Principal object when adding this as a parameter in the method.
However, this basicly only has the username in it, and I need the (extended) UserDetails object created during logging in.
SecurityContextHolder.getContext().getAuthentication() returns null. As I understood because spring creates a special session for handling the websocket connections.
The Question: Is there a way to access the securitycontext from inside the websocket session/thread?
(Being able to access a session bean would suffice as well).
#AuthenticationPrincipal is specifically for REST/MVC methods.
However, you can get pretty close by adding an argument of Type java.security.Principle to your #MessageMapping annotated method and then taking the real UserDetails object from it as follows:
FooUserDetails currentUser = (FooUserDetails) ((Authentication) user).getPrincipal();
This works for me for Spring Boot 1.5.4
I suppose you have extended AbstractWebSocketHandler
the you could have principal name :
#Override
public void afterConnectionEstablished ( WebSocketSession session ) throws Exception {
logger.info ( "afterConnectionEstablished = " + session.getPrincipal () );
}
I've not tested it, but you should be able to access your user adding a parameter like
#AuthenticationPrincipal CustomUser customUser
to your #MessageMapping method.
You can find more here: http://docs.spring.io/spring-security/site/docs/4.0.x/reference/htmlsingle/#mvc-authentication-principal

RequestDispatcher to a jsp or servlet

Parameters[userName, UserPW] are sent by the user through a home.jsp. These parameters are matched in Login servlet against a stored userInfo Db using JDBC.
In the doPost method I am using if condition tfor authentication as follows
if (rs.next()) {
String refName = rs.getString("UserName");
String refPass = rs.getString("userPW");
if (user.equals(refName) && pw.equals(refPass)) {
out.println("<br>You are In");
RequestDispatcher dispatch= getRequestDispatcher("/SearchFriend.jsp");
dispatch.forward(req, resp);
System.out.println("sucess");
}
When the authentication is successfull, How can i direct the user to a new jsp or servlet where he can input few textboxes and select-options to select few records from the Db table.
its not clear to me that How can I direct the page to a Search.jsp page in above If condition. The Search.jsp is in weBContent folder of Juno.
I am using JDBC with tomcat7. Please help
It is probably not clear , what exactly your requirement are and what you are trying to achieve by looking into the code you have posted.Kindly reframe your question
According to my assumption , you need to redirect the user to the home page when the authentication is successful.
If so, for that you can store the user credential in the session by making a custom filter say SessionFilter implements Filter
HttpSession session = request.getSession();
Store the credenials in the session and if authentication is successful then redirect using :
RequestDispatcher view = request.getRequestDispatcher(/home.jsp);
view.forward(req,resp);

asp.net mvc multiple connection strings

I am creating asp.net MVC Application using MVC 3.0. I have 2 users but the DataBase is the same. So, Is it possible to setup two connection strings or even more in web.config? when user login, I redirect it to his database, so then he can use his DataBase.
So major issue here is to find out which user is logged in and use connection string for that user.
I am using default mvc account controller and for example when i want to display welcome message for user in my view i type: if (#User.Identity.Name == "UserName") then some message
So where is the best place to find out which user is logged in and set his connection string in controller or in a view?
Yes, you can have as many connection strings in your web.config file as you want.
But, if you're designing a multi-tenant application than there are better ways of doing it than adding a connection string to web.config file every time a new user signs up.
Probably the best way for you is to have a single database where user-related tables have foreign keys to Users table.
You can learn more about multi-tenant architectures from this Microsoft article.
I agree with Jakub's answer: there are better ways of handling multi-tenancy than having a different database per user.
However, to answer your specific question, there are two options that come to mind:
You can set the connection string to a session variable immediately after login.
Your data access layer can choose the connection string based on the logged in user when it's created. (I'd recommend this over the first option)
To store the connection after login, if you're using the standard ASP.NET MVC Account Controller, look at the LogOn post action:
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(model.UserName, model.Password))
{
//EXAMPLE OF WHERE YOU COULD STORE THE CONNECTION STRING
Session["userConnectionString"] = SomeClass.GetConnectionStringForUser(model.UserName);
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
If you wanted to select the connection string when doing data access, your repository or data access layer will probably have a system for handling that. For instance with Entity Framework Code First, the DbContext constructor allows you to pass in the name of a connection string when you're creating it:
connectionString = SomeClass.GetConnectionStringForUser(model.UserName);
DbContext context = new DbContext(connectionString);
But again, I'd look at other ways of handling multitenancy unless your business dictates that your users have physically separate databases.
you can have multiple connection strings in web.config. Now if you want to use different connection string for different users there must be some criteria for division of users
<appSettings><add key="connectionString" value="Data Source=develope\sqlexpress;Initial Catalog=validation_tdsl;Integrated Security=True;Max Pool Size=1000;Connect Timeout=60000;"></add>
<add key="connectionString1" value="server=MARK\SQLEXPRESS;database=name;integrated security=true;Max Pool Size=1000;Connect Timeout=60000;"></add>
<add key="connectionString2" value="server=name\SQLEXPRESS;database=FM;integrated security=true;Max Pool Size=1000;Connect Timeout=60000;"></add>
and later you can use them like following
Dim con As New SqlConnection(System.Configuration.ConfigurationSettings.AppSettings("connectionString"))
Dim con1 As New SqlConnection(System.Configuration.ConfigurationSettings.AppSettings("connectionString1"))
EDIT : In c# it would be:
SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.AppSettings["connectionString"]);
SqlConnection con1 = new SqlConnection(System.Configuration.ConfigurationManager.AppSettings["connectionString1"])
Note: ConfigurationSettings is now obsolete.

HttpContext.User.Idenity is empty

I'm using asp.net and trying to assign roles for a user with forms authentication like this:
public ActionResult AdminLogin(string password, string username)
{
User _user = _us.GetUsers(username, password).FirstOrDefault();
if (_user != null)
{
string _username = _user.Username;
FormsAuthentication.SetAuthCookie(_username, false);
string[] _roles = _us.GetUserRoles(_username);
HttpContext.User = new GenericPrincipal(HttpContext.User.Identity, _roles);
return RedirectToAction("Index", "Admin");
When I debug HttpContext.User.Identity always is null, but _username and _roles contains the proper data. Howto fix this?
/M
Your action is setting the User IPrincipal for the current context. As soon as you redirect to your other action (and all subsequent requests) a new HttpContext is created with a null User IPrincipal.
What you could do is persist the information in the authentication cookie and then extract that data in the Application_AuthenticateRequest method in your Global.asax file and set the User property of the HttpContext there.
This answer contains more details and example code
I believe the issue is that you are just setting the user as authenticated, and therefore, the HttpContext is not updated yet since the auth cookie has not yet been set on the users side of the request.
I was struggling too.
I was trying to carryout my authentication and authorization inside a WCF service using standard ASP.Net Membership and Role providers.
I wanted to pass in credentials and a 'requested app' to determine if the user 'authenticated' for that app. (not the ASP.Net APP, but an app in my own database).
To do this, I wanted access to the roles, but didn't want to 'redirect' or have a second call to my WCF service.
Here is some code that works for me:
First I determine if the user is valid as follows:
if (Membership.ValidateUser(CompanyCn, CompanyPwd))
{
sbLogText.AppendFormat("\r\n\r\n\tValid User UID/PWD: '{0}'/'{1}'", CompanyCn, CompanyPwd);
FormsAuthentication.SetAuthCookie(CompanyCn, false);
}
Then the following code workes nicely for getting the list of roles:
List<string> roleList = new List<string>(Roles.GetRolesForUser(CompanyCn));
sbLogText.AppendFormat("\r\n\r\n\tUser ('{0}'): Roles ({1}):", CompanyCn, roleList.Count);
foreach (string s in roleList)
sbLogText.AppendFormat("\r\n\t\tRole: {0}", s);

Resources