custom authentication using only authorities by username query in spring security - spring

The following code
<jdbc-user-service data-source-ref="dataSource"
authorities-by-username-query="select USERNAME,ROLE from USERS where USERNAME=?"/>
</authentication-provider>
gives me error
org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]
Jan 14, 2014 10:17:40 PM org.springframework.jdbc.support.SQLErrorCodesFactory <init>
INFO: SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase]

I recommend implementing the interface UserDetails, you can check out this project:
https://github.com/pgardunoc/spring-security
The idea is to implement the interface and you will have more control.

Spring Form .I want to update the request made by customer by changing its status.some of field coming form controller .I want to submit form to controller in order to acess the values
h2>Update Request</h2>
>form:form method="POST" action="/my/update.htm" commandName="servicehistory">
table align="center" border="0">
<tr><td>Request Id: </td>
<td><form:input path="sr.ServiceRequestId" value="${sr.serviceRequestId}"></form:input> < other fields..............
<tr><td><input type="submit" value="Save" /></td></tr>
Controller which access the form value and update the request in database.but it is not happening.GUI displays resource is not available.It was working without Spring Security.
#RequestMapping(value="/my/update.htm",method=RequestMethod.POST)
public ModelAndView update(#ModelAttribute("servicehistory") #Valid ServiceHistories sh1,BindingResult result,ModelMap map)
{
Redirect it to another page after validating the form
return new ModelAndView(("redirect:/displaylist.htm"));
}
>Spring Security which implement security after matching url and user role
< http auto-config="true" use-expressions="true">
<intercept-url pattern="/admin/*" access="hasRole('Technician')" />
<intercept-url pattern="/my/**" access="hasRole('Techincian')" />

>This is JSp page that is used to assign the compalint to techincian. After hitting submit, it give number format exception
<c:forEach items="${hlist}" var="history" varStatus="i">
<tr>
<td><form:input path="requests[${i.index}].ServiceRequestId" value="${history.serviceRequestId }"></form:input></td>
<td><form:input path="requests[${i.index}].Description" value="${history.description }"></form:input></td>
<td><form:select multiple="false" path="requests[${i.index}].userto.UserId">
<form:option value="NONE" label="--- Select ---" />
<c:forEach items="${user}" var="u" varStatus="index">
<form:option label="${u.userName}" value="${u.userId}" />
</c:forEach>
</form:select>
</tr>
</c:forEach>
<tr><td> <input type="submit" value="Assign Technicians"></td></tr>
>Controller : I am using Autopopulating list to access list coming from above form.But it gives Number format exception because label contains String value and value attribute is an int. But it is working for another scenario which is identical to this one.
#ModelAttribute("requestForm")
public RequestForm getRequest()
{
RequestForm rf=new RequestForm();
rf.setRequests(new AutoPopulatingList(ServiceRequests.class));
return rf;
}
#RequestMapping(value="/admin/assigntech.htm",method=RequestMethod.POST)
public String assign(#ModelAttribute("requestForm") RequestForm requestForm,BindingResult result,ModelMap map)
{
List<ServiceRequests> sr=(List<ServiceRequests>)requestForm.getRequests();
System.out.println(sr.size());
System.out.println(sr.get(0).getUserto().getUserId());
return "Welcome";
}

Related

Fetch data from database using ajax in jsp and spring

i have dropdown a label in that already values are coming from database using spring jsp & mysql , now i need to apply ajax search in my dropdown or text box .How can i apply in my jsp spring forms ??
example:
controller#
#RequestMapping(value = "/addBank1")
public ModelAndView addBank(ModelMap model, #RequestParam String entityType) {
ArrayList<HashMap<String, String>> allbankAccounts = accService
.getAllbankAccounts(entityType);
model.addAttribute("allbankAccounts", allbankAccounts);
}
Jsp#
<p class="text-muted font-13">
<strong>Bank name </strong>
<span class="m-l-15">
<form:select class="form-
control" path="empQufnId" title="Select" id="report">
<form:option value="" label="Select
bank name" />
<c:forEach items="${allbankAccounts}"
var="sal" varStatus="status"
<form:option path="empQufnId"
value="${sal.bankId}" >${sal.bankName}</form:option>
</c:forEach>
</form:select>

Spring Security - Custom login form not calling the AuthenticationProvider on submit

RESOLVED:
Spring Security 4 no longer seems to provide a default login-processing-url. We must now explicitly provide it in form-login as follows.
login-processing-url="/j_spring_security_check"
I have a strange combination of behaviors that has me stumped. Found lots of tutorials and similar questions but none quite exactly like this. I hope someone can help.
Short version: The login page redisplays - regardless of good or bad username/password and the AuthenticationProvider is never called (breakpoints not tripped).
Long version:
Step 1 - successful
I was able to use spring security with the default AuthenticationProvider and the default auto-generated login screen. Good.
I was able to write a custom AuthenticationProvider and UserDetailsService. Things worked fine, using the default auto-generated login screen. Good.
... so the above rules out a lot of possible problems.
Step 2 - the problem - Setting up to use a custom login form
1) I added the form-login:
<sec:form-login
login-processing-url="/j_spring_security_check"
login-page="/login.htm"
authentication-failure-url="/login.htm?error"
username-parameter="username"
password-parameter="password"
/>
<sec:logout logout-success-url="/login.htm?logout"/>
<sec:csrf/>
2) I made sure that login URLs will be accessible:
<sec:intercept-url pattern="/login.htm" access="permitAll" />
3) I created a trivial LoginController:
#Controller
public class LoginController {
#RequestMapping(value="/login.htm")
public ModelAndView login(HttpServletRequest request,
#RequestParam(value="error", required=false) String error,
#RequestParam(value="logout",required=false) String logout) {
ModelAndView model = new ModelAndView();
if(error!=null) {
model.addObject("error", "Invalid username or password.");
}
if(logout!= null) {
model.addObject("msg", "Successfully logged out.");
}
model.setViewName("/login");
return model;
}
4) I created a trivial login.jsp:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>Login</title>
</head>
<body onload="document.loginForm.username.focus()">
<h1>Login form</h1>
<div>
<h2>Username and Password</h2>
<c:if test="${not empty error}">
<div style="color: red">${error}</div>
</c:if>
<c:if test="${not empty msg}">
<div style="color: green">${msg}</div>
</c:if>
<form name="loginForm" action="<c:url value='j_spring_security_check' />" method='POST'>
<table>
<tr>
<td>User:</td>
<td><input type='text' name='username' value = '' /></td>
</tr>
<tr>
<td>Password:</td>
<td><input type='password' name='password' /></td>
</tr>
<tr>
<td colspan='2'><input name="submit" type="submit" value="submit" /></td>
</tr>
<tr><td colspan='2'>[${not empty webUser}]</td></tr>
</table>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
</div>
</body>
</html>
5) Then I setup some breakpoints in Eclipse to see how it behaves.
The login page displays fine.
I enter username and password and hit submit.
Good or bad username and password all cause the same behavior, the redisplay of the login page.
The breakpoints in the AuthenticationProvider are never tripped.
My interpretation is that the action specified by < c : url value='j_spring_security_check' /> is not triggering the AuthenticationProvider.
Note that the very same custom AuthenticationProvider worked flawlessly when I used the built-in default spring security login form. That tells me that the problem has nothing to do with the provider itself, but rather with "reaching it" when I hit submit in login.jsp, especially since I have a breakpoint on its very first line and it is not being tripped.
I bet my error is trivial and obvious to someone familiar with Spring Security. My thanks in advance to anyone that catches it.
This question is resolved.
Spring Security 4 no longer seems to provide a default login-processing-url. We must now explicitly provide it in form-login as follows.
login-processing-url="/j_spring_security_check"
After banging my head against the wall for quite a few hours I stumbled upon the solution. I hope this is of help to others in the same situation.

Spring Framework 3.0.5 - spring form data binding - comma delimiter

I have a group editation form:
<form:form method="POST" action="" commandName="group">
<table>
<tr>
<td><form:label path="name">Name</form:label></td>
<td><form:input path="name" disabled="disabled" /></td>
<td><form:errors path="name" class="error" /></td>
</tr>
<tr>
<td><form:label path="description">Description</form:label></td>
<td><form:input path="description" /></td>
<td><form:errors path="description" class="error" /></td>
</tr>
<tr>
<td><form:label path="gidNumber">GID</form:label></td>
<td><form:input path="gidNumber" /></td>
<td><form:errors path="gidNumber" class="error" /></td>
</tr>
<tr>
<td colspan="3"><input type="submit" /></td>
</tr>
</table>
<form:hidden path="members" />
</form:form>
This form is binding object of class Group. Problem is with binding the member attribute to the hidden field. The deffinition of the memeber attribute in Group class is below. The group class is also being used by Spring LDAP ODM manager, (thus the annotations there).
#Attribute(name="member", syntax="1.3.6.1.4.1.1466.115.121.1.12")
private List<String> members = new ArrayList<String>();
The content of this array list is usually something like:
1: uid=user1,ou=users,dc=example,dc=com
2: uid=lilcuttie2,ou=users,dc=example,dc=com
3: uid=naprostejmagor,ou=users,dc=example,dc=com
4: uid=crazyuser,ou=users,dc=brazzers,dc=com
...
When the content is binded to hidden field it is concatenated to the comma delimited and then when it is beeing splited again to the arraylist entries, of course each entry is broken to four separate entries.
I've tried to use custom converter for ArrayList, but it messed up some otheer stuf like loading resource messages for locales..
Do you have any suggestions how to deal with it in any non-ugly way - so that I dont have to wrap my DAO classes nor modify them.
Thanks,
/Jakub
Have a small wrapper type over your members element, say:
public class MembersWrapper{
private List<String> members;
.....
}
Now, you can provide a custom converter to convert this MembersWrapper instance to a String and back - the conversion can be to say colon delimited across each element of the list, something that you can parse back later:
public class MemberWrapperToStringConverter implements Converter<MemberWrapper, String>{
...
}
public class StringToMemberWrapperConverter implements Converter<String, MemberWrapper>{
....
}
and register these converters with Spring MVC:
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="..MemberWrapperToStringConverter "/>
<bean class="..StringToMemberWrapperConverter "/>
</set>
</property>
</bean>
An alternative will be providing a custom property editor through #InitBinder annotation:
#InitBinder
public void initBinder(WebDataBinder binder){
binder.registerCustomEditor(Wrapper.class, new PropertyEditorSupport(){
#Override public String getAsText() {
//....
}
#Override public void setAsText(String text) throws IllegalArgumentException {
//....
}
});
}
The logic in these converters should be straightforward, convert the list to some string form, that you can parse back to list easily, say between list elements just add a colon or a semi-colon.
As I am not clear about your problem I have made some assumptions and providing this answer on basis of that.
Well you can use to loop your entries in the members list and for each entry in the list you can create a separate hidden field for that.
Hope this helps you.
Cheers.
You don't need to put the formtag for hidden field now when you are using just use the simple input tag for hidden fields but in the name property you need to specify as following.
<input type="hidden" name="members${status.index}"/>
in this way it will bind the same value back to the controller.
I think this should help you.
Cheers.

Spring MVC 3 Validation will not work when attributes added to model

I'm trying to get Spring annotation based validation working in a simple webapp. I'm using Spring 3.0.5, Tiles 2.2.2. In one specific case I can get the validation error to appear next to the field, however as soon as I add any objects to the model it stops working. Ideally, after the POST, I want to redirect to a GET of the form with the validation errors included. This is the setup:
I have a simple domain object.
public class DomainObject {
#NotEmpty
private String name;
private Date created;
private Date lastModified;
...
}
I have a controller with a GET method which adds all existing DomainObjects to the model and returns a view that displays them, and contains a very simple form for creating them. It also has a POST method for creating a new DomainObject.
#Controller
#RequestMapping("/")
public class DomainObjectController {
#Autowired
private DomainObjectService domainObjectService;
#RequestMapping("form.htm")
public String home(Model model) {
model.addAttribute("objects", domainObjectService.getAll());
model.addAttribute(new DomainObject());
return "form";
}
#RequestMapping(value="new_object.do", method=RequestMethod.POST)
public String newObject(#Valid DomainObject domainObject, BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
//model.addAttribute("objects", domainObjectService.getAll());
//model.addAttribute(new DomainObject());
return "form";
}
domainObjectService.saveNew(domainObject);
model.addAttribute("objects", domainObjectService.getAll());
model.addAttribute(new DomainObject());
return "form";
}
}
Here's the view:
<form:form commandName="domainObject" action="new_object.do" method="post>
<spring:message code="name" />: <form:input path="name" />
<input type="submit" value="<spring:message code="create.object"/>" /><form:errors path="name" cssClass="error"/></form:form>
</div>
<table class="centered">
<col width=50 />
<col width=225 />
<col width=200 />
<col width=200 />
<thead>
<tr>
<td id="id" class="sortable"><spring:message code="id" /></td>
<td id="name" class="sortable"><spring:message code="name" /></td>
<td id="created" class="sortable"><spring:message code="created" /></td>
</tr>
</thead>
<tbody>
<c:forEach var="obj" items="${objects}">
<tr>
<td class="id">${obj.id}</td>
<td>${obj.name}</td>
<td>${obj.created}</td>
</tr>
</c:forEach>
</tbody>
</table>
With this setup, if I leave the name field empty, the validation error is picked up and correctly displayed to the right of the field. However, the table is always empty, as no objects are added to the model. If I add objects to the model, by uncommenting the lines
//model.addAttribute("objects", domainObjectService.getAll());
//model.addAttribute(new DomainObject());
the table is populated but the validation error no longer appears. I can't work this one out.
As another unwanted side effect, any relative links I have in the view now no longer work (for example, a link which changes the locale href="?lang=de").
So, what could be causing the validation message to disappear when I add data to the model? And is it possible for me to redirect to the original form while keeping hold of the validation messages?
Thanks,
Russell
The validation error is attached to the object that is invalid. If you replace the object that is invalide by an new one:
model.addAttribute(newDomainObject());
then the error messages is not attached to this object.

Why do I get IllegalArgumentException Cannot convert value of type String to required type Product, in Spring?

I receive the exception
Failed to convert property value of
type [java.lang.String] to required
type [beans.Product] for property
product; nested exception is
java.lang.IllegalArgumentException:
Cannot convert value of type
[java.lang.String] to required type
[beans.Product] for property product:
no matching editors or conversion
strategy found
in the Errors errors object even before my DetailProductValidator starts validating through the validate method.
I don't understand why Spring does that. I don't have any input field that is mapped directly to the product property/object. I just use the product object's properties in the jsp. For example, I use:
<form:options items="${dpBackObj.product.colorMap}"/>
<!-- or -->
${dpBackObj.product.priceInDollars}
but I never use:
<form:input path="product"/>
Can anyone please explain why this happens? And maybe inform me of a simple solution?
The bean configuration for the controller is:
<!-- DETAIL PRODUCT FORM CONTROLLER -->
<bean id="productDetailFormController" name="/detail.htm /addToCart.htm"
class="detailProduct.DetailProductFormController">
<property name="sessionForm" value="true" />
<property name="commandName" value="dpBackObj" />
<property name="commandClass" value="detailProduct.DetailProductBackingObject" />
<property name="validator">
<bean class="detailProduct.DetailProductValidator" />
</property>
<property name="formView" value="detail" />
<property name="successView" value="redirect:/viewCart.htm" />
<property name="cartService" ref="cartServiceImpl"/>
</bean>
The backing object for the DetailProductFormController is:
public class DetailProductBackingObject {
private String quantityOverflowError;
private Product product;
private int quantity;
private ShoppingCart shoppingCart;
private long sizeId;
private long colorId;
public DetailProductBackingObject() {
this.product = new Product();
this.sizeId = -1;
this.colorId = -1;
}
//getters and setters
}
If you need some other info, I will provide. I am using Spring 2.5.5.
Kind Regards,
Despot
EDIT1 (due to request from axtavt):
<form:form method="post" commandName="dpBackObj">
<table width="730" border="0" cellspacing="0" cellpadding="0">
<c:if test="${!empty dpBackObj.quantityOverflowError}">
<tr>
<td>
<c:out value="${dpBackObj.quantityOverflowError}"/>
</td>
</tr>
</c:if>
<spring:bind path="dpBackObj.*">
<c:if test="${not empty status.errorMessages}">
<div class="val-summary text-error" id="errorDivId">
<div style="" class="val-summary text-error" id="errorDivId">
<fmt:message key="detail.error.header"/>
<ul>
<c:forEach items="${status.errorMessages}" var="error">
<li><c:out value="${error}"/></li>
</c:forEach>
</ul>
</div>
</div>
</c:if>
</spring:bind>
<tr>
<td width="310" align="left" valign="top">
<img src="${imagesPath}/${dpBackObj.product.largeImageUrl}" alt="${dpBackObj.product.description}" />
</td>
<td width="420" align="left" valign="top">
<div id="tls_detPName">
<c:out value="${dpBackObj.product.name}"></c:out>
</div>
<div >
<strong class="numeric">${dpBackObj.product.priceInDollars}</strong>
</div>
<div id="tls_detPDescLong">
${dpBackObj.product.largeDescription}
<br />
</div>
<div >
<table cellpadding="2" border="0">
<tr>
<td align="right">
<label for="p_sizes" class="label"><fmt:message key="viewCart.Size"/></label>
</td>
<td>
<form:select path="sizeId" >
<form:option value="-1" label="x"/>
<form:options items="${dpBackObj.product.sizeMap}"/>
</form:select>
</td>
</tr>
<tr>
<td align="right">
<label for="p_colors" class="label"><fmt:message key="viewCart.Color"/></label>
</td>
<td>
<form:select path="colorId" >
<form:option value="-1" label="y"/>
<form:options items="${dpBackObj.product.colorMap}"/>
</form:select>
</td>
</tr>
</table>
</div>
<div id="tls_addToCart">
<div >
<label for="quantityId" class="label"><fmt:message key="viewCart.Quantity"/>:</label>
<form:input path="quantity" onkeypress="return checkForNumber(this, event)" maxlength="10" size="3" id="quantityId" cssClass="textbox-center"/>
<input type="image" name="addToCartButtonName" src="${imagesPath}/addToCartBtn.jpg" />
</div>
</div>
</td>
</tr>
</table>
</form:form>
EDIT2 (due to JacobM's request):
This is my Validator:
public class DetailProductValidator implements Validator {
public boolean supports(Class clazz) {
return DetailProductBackingObject.class.equals(clazz);
}
public void validate(Object obj, Errors errors) {
DetailProductBackingObject detailProductBackingObject = (DetailProductBackingObject) obj;
if (detailProductBackingObject.getSizeId() == -1) {
errors.rejectValue("sizeId", "error.detail.jsp.choose.size", null, "Input size.");
}
}
}
When I reach the line DetailProductBackingObject detailProductBackingObject = I already have the error.
The converting of the request parameters to the backing object properties happens in http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/web/servlet/mvc/BaseCommandController.html . This is what Spring says about the conversion:
Populating using request parameters
and PropertyEditors: Upon receiving a
request, any BaseCommandController
will attempt to fill the command
object using the request parameters.
This is done using the typical and
well-known JavaBeans property
notation. When a request parameter
named 'firstName' exists, the
framework will attempt to call
setFirstName([value]) passing the
value of the parameter. Nested
properties are of course supported.
For instance a parameter named
'address.city' will result in a
getAddress().setCity([value]) call on
the command class.
It's important to realise that you are
not limited to String arguments in
your JavaBeans. Using the
PropertyEditor-notion as supplied by
the java.beans package, you will be
able to transform Strings to Objects
and the other way around. For instance
setLocale(Locale loc) is perfectly
possible for a request parameter named
locale having a value of en, as long
as you register the appropriate
PropertyEditor in the Controller (see
initBinder() for more information on
that matter.
Validators: After the controller has
successfully populated the command
object with parameters from the
request, it will use any configured
validators to validate the object.
Validation results will be put in a
Errors object which can be used in a
View to render any input problems.
Since I can't see anything wrong with the form, the only possible reason I can imagine is that you have a parameter named product in the URL of your form page.
If so, you can change your URLs or use DataBinder.setDisallowedFields() to disable the attempt to bind that parameter.

Resources