I have a question with Spring MVC RequestMapping annotation. need your help.
I have created one IPSLcontroller and i want that IPSLcontroller to handle all request url.i have created two method in this controller.
1)handleLogoutRequest :- this method should invoke on below url.
2)handleRequest :- this method should invoke on all request url otherthan logout.
http://localhost:9086/webapp/login
or
http://localhost:9086/webapp/add
or
http://localhost:9086/webapp/remove
here is my sample code. but it's not working as expected.
#Controller
public class IPSLController {
#RequestMapping(value={"/logout/*"},method = RequestMethod.POST)
protected void handleLogoutRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
System.out
.println("........................IPSLController logout request.......................................");
}
#RequestMapping(method = RequestMethod.POST,value={"/*"})
protected void handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
System.out
.println("........................IPSLController all request Post.......................................");
}
}
You should use a general Prefix for every controller you use, so you can differ between them better. Also you donĀ“t need any "/" for calls like this.
#Controller
#RequestMapping("ispl")
public class IPSLController {
#RequestMapping(value={"logout"},method = RequestMethod.POST)
protected void handleLogoutRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
System.out
.println("........................IPSLController logout request.......................................");
}
#RequestMapping(method = RequestMethod.POST,value={"hello"})
protected void handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
System.out
.println("........................IPSLController all request Post.......................................");
}
}
If you now want to call them over a ServletRequest or with a restService or something similar you should declare them like this
#GET
#Path("ispl/logout")
public void Method (HttpServletResponse ...)
Well it is working the way it should. You have a mapping for /* and for /logout/*. So when you post to /logout it invokes the method for /*. I suspect that if you post to /logout/something it would invoke your logout handler.
If you want it to work, you cannot have a wildcard mapping for the second method. At least use /something/* so that spring can make a correct decision on mappings.
Related
I have a servlet class which has a method "process", over ridden from HttpServlet
#override
protected void process(HttpServletRequest request, HttpServletResponse response) {
InputStream in = null;
OutputStream out = null;
String inXml = null;
//some more code..
}
It is reading whatever is coming into the servlet.
How can I rewrite this as rest controller in spring??
Just code it as:
#RestController
public ReturnType process(HttpServletRequest request, HttpServletResponse response {
//...
}
and check this part of the Spring MVC documentation as well:
#RequestMapping handler methods have a flexible signature and can choose from a range of supported controller method arguments and return values.
Note, that:
whatever you return from your Rest-Controller turns into HTTP Response Body;
you can define #RestController on the class level.
I have a Spring MVC controller and want to secure it with Spring Method Security.
In the following example it works - #RequestMappingand #PreAuthorizeannotate the same method:
#Controller
public class MyController {
#RequestMapping(value = "/test", method = {RequestMethod.POST, RequestMethod.GET})
#PreAuthorize("isAuthenticated()")
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
return test(request, response);
}
public ModelAndView test(HttpServletRequest request, HttpServletResponse response) throws Exception {
...
}
In this example it does not work - #RequestMappingand #PreAuthorizeannotate different methods:
#Controller
public class MyController {
#RequestMapping(value = "/test", method = {RequestMethod.POST, RequestMethod.GET})
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
return test(request, response);
}
#PreAuthorize("isAuthenticated()")
public ModelAndView test(HttpServletRequest request, HttpServletResponse response) throws Exception {
...
}
What might be the reason for this strange behaviour?
In the second example the test method is being called directly from the handleRequest method. Spring has no mechanism to intercept method calls from with in the same class. Thus, the Proxy / AOP method inception for #PreAutorize is never invoked.
More on the topic of Spring Proxy
I've setup a Spring HandlerInterceptor to add an attribute to the HttpServletRequest to be able to read it from the Controller, sadly this does not seem to work which seems strange to me. Am I doing things wrong? Any idea how to transmit the data from the Interceptor to the Controller?
Here is the simplified code of the two impacted classes
public class RequestInterceptor implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
request.setAttribute("my-role", "superman");
}
[...]
}
#RestController
#RequestMapping("Test")
public class TestController {
public final Logger logger = LoggerFactory.getLogger(getClass());
#RequestMapping(value = "something")
public void something(HttpServletRequest request) {
logger.info(request.getAttribute("my-role"));
}
[...]
}
The request.getAttribute("my-role") returns null... but does return the excepted value if I read it in the postHandle of the HandlerInterceptor, I feel like I'm missing something...
EDIT : I found out that going thru the session with "request.getSession().setAttribute" works as a charm, still i do not understand why the request itself does not work in this use case.
Can you try with session instead of request like below.
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
...
HttpSession session = request.getSession();
session.setAttribute("attributeName", objectYouWantToPassToHandler);
....
}
In your handler handleRequest method:
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
....
HttpSession session = request.getSession();
objectYouWantToPassToHandler objectYouWantToPassToHandler = session.getAttribute("attributeName");
....
}
I have a CustomLoginSucessHandler in my Spring MVC 4 project to manage an action when the user Logs In.
This is working properly. In the same class I have the method determineTargetUrl to redirect the user according to his ROLE.
Here is the code:
#Override
protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response){
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
final String userName = authentication.getName();
log.debug("TARGET URL METHOD!");
List<Authority> authorityList = authorityService.getAllAuthoritiesByUserName(userName);
for(Authority authority: authorityList){
switch (authority.getAuthority()){
case "ROLE_ADMIN":
return "processFile";
case "ROLE_USER":
return "userPortal";
case "ROLE_DEMO1":
return "processFile";
case "ROLE_DEMO2":
return "processFile";
}
}
return "403";
}
See that I have a log.debug("TARGET URL METHOD")
This log is never called and of course the page is not being redirected, it's going to the default landing page that is processFile.html.
I am puzzled why the second method is not being called while my onAuthenticationSuccess works perfectly. They are in the same Class.
Here is the code how I create the instance of my CustomLoginSucessHandler:
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private DataSource dataSource;
#Autowired
private CustomLoginSucessHandler customLoginSucessHandler;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().formLogin().loginPage("/login.html")
.loginProcessingUrl("/login").permitAll().and().logout().logoutSuccessUrl("/")
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")).permitAll().and().exceptionHandling()
.accessDeniedPage("/403.html");
http.csrf().requireCsrfProtectionMatcher(new CsrfRequestMatcher());
http.formLogin().successHandler(customLoginSucessHandler);
}
Thank you.
You are trying to ovverride the wrong function, that is the root cause of your issue. In the excerpt you provided you have a function that seems to be overriding another:
#Override
protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response){
but in fact it is not overriding anything. If you check the javadoc of AuthenticationSuccessHandler, you will see that it provides only one function: onAuthenticationSuccess which you reported as "working". It works, but it is an overriden function and it does get called as part of the standard login procedure. If you follow closely this example:
CustomLoginSuccessHandler example (probably you followed this already)
you will see that the determineTargetUrl function is not overriden, but explicitly called by the implementation:
protected void handle(HttpServletRequest request,
HttpServletResponse response, Authentication authentication) throws IOException {
String targetUrl = determineTargetUrl(authentication);
which handle method in turn is also being called from:
#Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication) throws IOException {
handle(request, response, authentication);
clearAuthenticationAttributes(request);
}
I have a MultiActionController with an action that I would only like to be reachable if the POST method is used.
public class MyController extends MultiActionController {
public ModelAndView myAction(final HttpServletRequest request, final HttpServletResponse response) throws Exception {
// I don't want to hit this code unless POST was used
}
}
Is there a way to achieve this through annotations or am I stuck checking request.getMethod() ?
Use:
#RequestMapping(value={"action1","action2","action3"},
method = RequestMethod.POST)