Spring Security: How do I reset SPRING_SECURITY_LAST_EXCEPTION.message? - spring

I am able to display the SPRING_SECURITY_LAST_EXCEPTION.message ("Bad Credentials") when a user tries to log in with incorrect credentials.
My login jsp currently uses the following code:
<c:if test="${not empty SPRING_SECURITY_LAST_EXCEPTION.message}">
<c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}" />
</c:if>
My problem is that the "Bad Credentials" message is still there when the user navigates away from the login page and then comes back.
How can I reset SPRING_SECURITY_LAST_EXCEPTION.message when a user refreshes the login page?

The typical approach is to display error message only after failed login, where failed login is determined by request parameter. That is, you configure Spring Security as
<form-login ... authentication-failure-url = "/login?error=1" />
and show error message as
<c:if test="${not empty param['error']}">
<c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}" />
</c:if>
However, since SPRING_SECURITY_LAST_EXCEPTION is a session attribute, I guess you can reset it using the following approach:
<c:remove var = "SPRING_SECURITY_LAST_EXCEPTION" scope = "session" />

For me it was more easy at this way
<c:if test="${param.error != null}">
<c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}" />
</c:if>
So you don't worry about removing vars and change the default URL,if there is some error it will be print as the URL got defined as parameter ?error and the exception will be printed (if you pass the parameter error manually nothing will happen because the exception does't exist).

Related

How do I write an if statement in JSP-JSTL if I need to check whether the user list contains a specific user?

'theGroup' and 'groupCreator' are a model(entity) attributes coming from the controller. 'users' is the array list which is the attribute of theGroup (theGroup.getUsers() basically).
I need to check if the groupCreator exists in theGroup.users list in JSP
I've tried the code below but it didn't work
<c:if test = "${theGroup.users.contains(groupCreator)}">
</c:if>
You can use forEach to iterate through values and then compare values in it with groupCreator. Your code will somewhat look like below :
<c:forEach var="values" items="${theGroup.users}">
<c:if test="${values == groupCreator}">
<!--setting true if value match-->
<c:set var="Matched" value="true" scope="request" />
</c:if>
</c:forEach
<!--Print-->
${Matched}

jstl conditional not working

I'm trying to separate my Java Code from my JSP files and I'm having a bit of a problem. I'm trying to find out whether the user is a guest or not and then printing the appropriate action EG login form or their Username.
Heres my index.jsp file:
<% if(view.guest) { %>
<%= "Scriptlet: Login Form Here" %>
<% } else { %>
<%= "Scriptlet: User Name Here" %>
<% } %>
<br/><br/>
<c:choose>
<c:when test="${view.guest eq true}">
JSTL Tag: Login Form Here
</c:when>
<c:otherwise>
JSTL Tag: User Name Here
</c:otherwise>
</c:choose>
This produces the following output:
Scriptlet: Login Form
JSTL Tag: User Name
As you can see the Scriptlet produces the expected results, but the JSTL tags produce the opposite. Infact if I reverse the JSTL's conditional to false (for debugging purposes) it still produces the same result "JSTL Tag: User Name"
Btw view.guest is a public boolean variable of the object view.
The JSP EL doesn't access local variables. It accesses attributes of the page, request, session or application scope. And it also assumes you're not using public fields (which should never be used), but respect the Java Bean conventions.
And, just as in Java, comparing a boolean with true is unnecessary. You just need
<c:when test="${view.guest}">
And the condition will evaluate to true if there is a page, request, session or application attribute named "view", having a public getGuest() or isGuest() method returning true.
If you didn't use scriptlets at all, you would never have local variables in your pages, and you would never have this problem.

Spring MVC : How to pass Model object from one method in controller to another method in same controller?

I have integrated Spring Security in my application , and would like to display an error message to the user in case of Bad credentials.
jsp:
<c:out value='${secerror}' /> //prints nothing on screen
<c:if test="${empty secerror}">
error is empty or null. //always prints this line on screen
</c:if>
<c:if test="${not empty secerror}">
<div class="errorblock">
Your login attempt was not successful, try again.<br /> Caused :
${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}
</div>
</c:if>
<c:set var = "url" value = "/j_spring_security_check" />
<form:form method="post" commandName="portalLogin" action="${pageContext.servletContext.contextPath}${url}" name="f">
[Update]: Sorry all, i realized that my Model object was getting overriden after i redirect to portalLogin.html as i had created a new model object created there previously.
But i tried few easy options by which i can pass Model object from one controller method to another method in the same controller. But nothing worked.
I tried using forward: prefix instead of redirect prefix. For this, i didn't get error message at all.
I tried below code in loginerror method.
return new ModelAndView("portalLogin","secerror","true");
I was getting following error for the above code:
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'portalLogin' available as request attribute
I did come across this link, but i found it to be a very lengthy solution and wasn't sure if iv'e to write that much code.
I wasn't sure if i can use Model object for #ModelAttribute annotations#ModelAttribute.
Please provide me with code snippets / examples which i can try out.
My controller method is like this:
#RequestMapping("/portalLogin")
public ModelAndView goToLogin(Model model) {
try {
System.out.println("Enter goToLogin************************");
} catch (Exception exception) {
}
return new ModelAndView("portalLogin", "portalLogin", new LoginModel());
//return new ModelAndView("portalLogin", model);
}
#RequestMapping(value="/loginfailed", method = RequestMethod.GET)
public ModelAndView loginerror(ModelMap model) {
//model.addAttribute("secerror", "true");
//return "redirect:portalLogin.html";
return new ModelAndView("portalLogin","secerror","true");
}
[Update]: As a work around i added goToLogin method logic inside loginerror method as my only intention is to get portalLogin page. Error was thrown as expected.
#RequestMapping(value="/loginfailed", method = RequestMethod.GET)
public ModelAndView loginerror(Model model) {
model.addAttribute("secerror", "true");
return new ModelAndView("portalLogin", "portalLogin", new LoginModel());
}
But still i would like to know if i can pass Model object from one controller method to another method in the same controller through some way.
You can also try something like this
<c:if test="${not empty secerror == 'true'}">
<tr>
<td colspan="2" align="center"><font style="color: red">Your login attempt was not successful, try again</font>
</td></tr></c:if>
Let`s make things easy, if you want to show a Bad credentials message, you can simply do something like this:
In your spring-security.xml:
<sec:form-login login-page="/login.jsp"
default-target-url="/default-url-when-login-correct"
authentication-failure-url="/login.jsp?error=true"
login-processing-url="/login" always-use-default-target="true" />
In your login.jsp:
<c:if test="${not empty param.error}">
<span>${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}</span>
</c:if>

spring:bind error using in a List

I have a list containing users. I am trying to print it in JSP but some how I am not able to get it to print it. Getting this exception HTTP Status 500 - javax.servlet.ServletException: javax.servlet.jsp.JspTagException: Neither BindingResult nor plain target object for bean name 'users[0]' available as request attribute
Code in JSP
<c:forEach items="${users}" var="user" varStatus="status">
<spring:bind path="users[${status.index}].name">
<c:out value="${status.value}" />
</spring:bind>
</c:forEach>
Controller
ModelAndView modelAndView = new ModelAndView("go_some_JSP_page");
List<UserEntity> users = userManager.getAllObjects();
modelAndView.addObject("users", users);
BTW, UserEntity has name field. If I remove the binding and try to print the user.name using <c:out value="user.name" /> it prints the value
Where am I going wrong and what do I need to do? Thanks
Not working code below. [I have to invoke formatting on field #NumberFormat so have to try it using status variable]
<spring:bind path="user.name">
<c:out value="${status.value}" />
</spring:bind>
Gets this error --> javax.servlet.ServletException: javax.servlet.jsp.JspTagException: Neither BindingResult nor plain target object for bean name 'user' available as request attribute
So added a bean binding and then I get empty table :(. I believe thats because the instance is empty. So this does not seems like a right approach.
#ModelAttribute("user")
public UserEntity userEntityBinding() {
return UserEntity.newInstance();
}
A working code exists at https://github.com/hth/StatusInvoke.git
Let me know if you face any problem deploying it.
This question has been solved. Thanks for looking at it.
You can try using LazyList instead of simple list. If you want to take a look at the example then you can refer one of my question. In the question statement I have mentioned how to use the LazyList.
Hope that helps you. Cheers.
this, if the modelandview are returned, is the correct way to populate the list
ModelAndView modelAndView = new ModelAndView("go_some_JSP_page");
List<UserEntity> users = userManager.getAllObjects();
modelAndView.addObject("users", users);
And this is the correct way to reference the list
<c:forEach items="${users}" var="user" varStatus="status">
<spring:bind path="user.name">
<c:out value="${status.value}" />
</spring:bind>
</c:forEach>
Your problem must be elsewhere is the name field definitely populated, is the correct jsp being called... the above code is correct and should work.
The correct answer to invoke #NumberFormat annotation is by using spring:eval expression tag
<spring:eval expression="user.balance" />
This invokes the annotation and performs formatting as mentioned in the annotation
I don't think you can use spring:bind in that case, AFAIK it tries to get the variable from the ModelMap, it's not able to get it from the "for" var.

Not able to retrieve session/request scope values using JSTL

In my xhtml page am setting values in some myValue variable. Code is as below,
<body>
<c:set var="myValue" value="someValue" scope="request"></c:set>`
</body>
Am hitting a login.jsp (Login page) from this xhtml page and trying to print the value on my login.jsp as below,
myValue ID retrieved from request <c:out value="${param.myValue}" />
This is not printing someValue. I also checked by putting it in session scope like below,
<c:set var="myValue" value="someValue" scope="session"></c:set>
Even this is not working
And in login.jsp,
myValue ID retrieved from session <c:out value="${sessionScope.myValue}" />
You should have just ${myValue}, as param.myValue means to find value from URL params.

Resources