Use different viewresolver depending on request - java

I try to solve the following problem:
I have set up my own viewResolver, adding a header and footer to all my requests (thanks, stackoverflow ;p). This works fine.
Problem is that my ajax-requests, that return a view to a specific container, also automatically get the header and footer which of course is not intended.
How can I get the viewResolver to act different if a request contains '/ajax/'? Actually, the jstl-Viewer works fine for them, but at the moment, my own resolver is the only one used because I don't know how to tell spring to act different on '/ajax/'.
Here my own resolver, pretty simple, just taken from here:
public class ViewTemplate extends InternalResourceView {
#Override
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
String dispatcherPath = prepareForRendering(request, response);
request.setAttribute("partial", dispatcherPath.substring(nthOccurrence( dispatcherPath, '/' , 2 ) + 1));
RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/views/layout.jsp");
rd.include(request, response);
}
// more functions like nthOccurrence
}
Do I have to tell this resolver that if indexOf("/ajax/") != -1 jstView needs to be called? And if yes, how?
Or am I doing it completely wrong? I would like to keep my header/footer as they are for all non-ajax-requests!
Any help appreciated!
Thanks!

You have put the code for a View not a ViewResolver right, I think a good solution could be to chain the ViewResolvers - just declare a new ViewResolver for your ajax views. For the Ajax related views, let this view resolver return a value, else return null, this will automatically get the ViewResolver to consider the next ViewResolver in the chain which can be your current ViewResolver.
eg.
<beans:bean id="ajaxViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="order" value="1"></beans:property>
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="viewNames">
<beans:list>
<beans:value>ajax*</beans:value>
</beans:list>
</beans:property>
<beans:property name="suffix" value=".jsp" />
</beans:bean>
In the above case, if you return your view name from a controller as "ajaxsomeview" then it will be handled by ajaxViewResolver, if you return "somethingelse" it will be handled by your current ViewResolver.

Related

Does Spring Security go well with custom authentication and authorization code?

I'm working on a REST service provider web application with Java + Spring and I wonder if I can fuse my in-house authentication and authorization code with Spring Security?
To be more specific, I have two methods (that I like to keep):
User authenticate(String username, String password) { ... }
boolean authorize(User user, String resource) { ... }
In this scenario, a REST API is a resource and the second method verifies whether it can be called by the user or not.
My question is if I switch to Spring Security then should I give in to it and annotate my methods with user names and role names!? Or is there a way that I can keep my way of thinking (that REST APIs are resources and annotating them with user names and role names is like hard-coding ACL)?
I know my question is somewhat vague but I've been struggling with it for some time now and I'll be really grateful if someone can give a straight answer.
You can inject your own authentication manager with password encoder.
Below is a post where I posted some questions about it a while ago. It's not an exact answer for you but it will lead you down the right track.
debug spring security authentication-manager
At the time I did it xml style but I'm sure you can change this to a java config style.
It definitely worked foe me!
Spring security also very useful for providing authentication and authorization to the REST URLs. We no need to specify any custom implementations.
First, you need to specify the entry-point-ref to restAuthenticationEntryPoint in your security configuration as below.
<security:http pattern="/api/**" entry-point-ref="restAuthenticationEntryPoint" use-expressions="true" auto-config="true" create-session="stateless" >
<security:intercept-url pattern="/api/userList" access="hasRole('ROLE_USER')"/>
<security:intercept-url pattern="/api/managerList" access="hasRole('ROLE_ADMIN')"/>
<security:custom-filter ref="preAuthFilter" position="PRE_AUTH_FILTER"/>
</security:http>
Implementation for the restAuthenticationEntryPoint might be as below.
#Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException ) throws IOException {
response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized" );
}
}
After this you need to specify RequestHeaderAuthenticationFilter. It contains the RequestHeader key. This is basically used for identifying the user`s authentication. Generally RequestHeader carries this information while making the REST calls.
For example consider below code
<bean id="preAuthFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
<property name="principalRequestHeader" value="Authorization"/>
<property name="authenticationManager" ref="authenticationManager" />
</bean>
Here,
<property name="principalRequestHeader" value="Authorization"/>
"Authorization" is the the key presented the incoming request. It holds the required user`s authentication information.
Also you need to configure the PreAuthenticatedAuthenticationProvider to fulfill our requirement.
<bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
<bean id="userDetailsServiceWrapper"
class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<property name="userDetailsService" ref="authenticationService"/>
</bean>
</property>
</bean>
This code will work for securing the REST urls by means of Authentication and authorization without any custom implementations.
My suggestion is go with Spring-AOP for custom authentication and authorization, if you want custom implementation for authentication and authorization which works similar to the spring security.
For Complete code please find the below link:
https://github.com/srinivas1918/spring-rest-security
I hope that, i understood your question.

Converting array of Object to JSON and send it over HTTP

I have an array of object as ArrayList which I want to convert to JSON and send it to client over HttpResponse using Java and Jackson.
How I can do this?
Assuming you already put jackson library and using Spring framework. Mentioned following line in your spring context file.
<!-- Configure to plugin JSON as request and response in method handler -->
<beans:bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<beans:property name="messageConverters">
<beans:list>
<beans:ref bean="jsonMessageConverter" />
</beans:list>
</beans:property>
</beans:bean>
and Return the List/Map/Object from controller and it will internally convert it to JSON
For Non Spring:
doPost(HttpServletRequest req, HttpServletResponse resp)
{
ObjectMapper mapper = new ObjectMapper();
ArrayNode rootNode = mapper.readValue(req.getReader(), ArrayNode.class);
}
Source:
Passing array from javascript to java servlet using Jackson
http://software.danielwatrous.com/restful-java-servlet-serializing-tofrom-json-with-jackson/
Hope this helps :)
Do share your environment details if it was still not helpful and i will try to help :)

Turn off automatic view resolution spring 4

I am using the spring MVC template in IntelliJ to create a webservice to produce JSON from a rest call.
package com.planit.mvc;
#RestController
#RequestMapping("/rest")
public class BasicRestController {
#RequestMapping(value = "/test/{name}", produces = MediaType.APPLICATION_JSON_VALUE)
public Person test(#PathVariable String name) {
Person p = new Person();
p.setAge(10);
p.setFirstName(name);
p.setLastName(name);
return p;
}
}
The servlet dispatcher XML is as follows:
<context:component-scan base-package="com.planit.mvc"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
So when I navigate to the URL it throws an error as it's trying to resolve a view based on the {name} param of the URL.
What is the correct way to achieve what I am looking, while still allowing for automatic view resolution?
EDIT: When I call the url such as:
http://localhost:8080/rest/test/variable
So hitting the BasicRestController, with the method test due to the /test section of the url, followed by the PathVariable "variable" I get this error in tomcat:
HTTP Status 404 - /WEB-INF/views/rest/test/variable.jsp
So it looks like its trying to resolve the view variable.jsp which of course does not exist. I simply want it to give me back the JSON representation of the Person object, and not have to render it into a view.
I believe you're just missing <mvc:annotation-driven/> from your servlet context configuration. Don't forget to add the namespace declarations and schemaLocation values.

AuthenticationSuccessHandler example for Spring Security 3

I am a newbie to Spring Security 3 . I am using roles for users to login.
I want to redirect a user to a different page based on the role of that user, I understand is that I would have to implement the AuthenticationSuccessHandler for the same, but some examples in that direction would help.
Thanks in advance,
Vivek
You can do something like this:
public class Test implements AuthenticationSuccessHandler {
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
Set<String> roles = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
if (roles.contains("ROLE_USER") {
response.sendRedirect("/userpage");
}
}
}
In the XML config add this:
<bean id="authenticationFilter" class="YOUR_AUTH_FILTER_HERE">
<!-- There might be more properties here, depending on your auth filter!! -->
<property name="authenticationSuccessHandler" ref="successHandler" />
</bean>
<bean id="successHandler" class="Test"/>

how to display custom error message in jsp for spring security auth exception

I want to display custom error message in jsp for spring security authentication exceptions.
For wrong username or password,
spring displays : Bad credentials
what I need : Username/Password entered is incorrect.
For user is disabled,
spring displays : User is disabled
what I need : Your account is diabled, please contact administrator.
Do I need to override AuthenticationProcessingFilter just for this ? or else can I do something in jsp itself to find the authentication exception key and display different message
Redefine the properties in messages.properties inside spring security jar. For example add to the classpath myMessages.properties and add a message source to the context:
AbstractUserDetailsAuthenticationProvider.badCredentials=Username/Password entered is incorrect.
AbstractUserDetailsAuthenticationProvider.disabled=Your account is diabled, please contact administrator.
At Salvin Francis:
Add myMessages.properties to the WAR file inside WEB-INF/classes.
Add this bean to spring context config file
Message Source Bean
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>myMessages</value>
</list>
</property>
</bean>
After adding the "messageSource" bean, I had problems to get the Error Message work with the CookieLocaleResolver because the DispatcherServlet (which does use this for your application automatically) is invoked after the Security.
See: http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#localization
My Solution was a custom Filter which sets the LocalContextHolder:
public class LocaleContextFilter extends OncePerRequestFilter {
private LocaleResolver localeResolver;
public void setLocaleResolver(LocaleResolver localeResolver) {
this.localeResolver = localeResolver;
}
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
// store Local into ThreadLocale
if (this.localeResolver != null) {
final Locale locale = this.localeResolver.resolveLocale(request);
LocaleContextHolder.setLocale(locale);
}
try {
filterChain.doFilter(request, response);
} finally {
LocaleContextHolder.resetLocaleContext();
}
}
}
And the Spring Security Context configuration:
<http use-expressions="true">
<custom-filter ref="localeContextFilter" after="FIRST" />
.....
</http>
<beans:bean id="localeContextFilter" class="at.telekom.ppp.util.opce.fe.interceptor.LocaleContextFilter" >
<beans:property name="localeResolver" ref="localeResolver" /><!-- e.g.: CookieLocaleResolver -->
</beans:bean>
I hope this helps others which has this problem.
Here is a JSP EL fix for this. More of a hack than an elegant solution, but gets the job done quick and dirty. Caveat- this is not i18n safe! Only English.
This requires the functions tag library:
<%# taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
And the replace code:
${fn:replace(SPRING_SECURITY_LAST_EXCEPTION.message, 'Bad credentials', 'Username/Password are incorrect')}
I am new to spring, but try this at the server:
throw new BadCredentialsException("This is my custom message !!");
Of course you need a class that is an authentication provider for this to work.

Categories

Resources