Spring Security: #PreAuthorize works only together with #RequestMapping - java

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

Related

Changing httpservletrequest to restcontroller in Spring

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.

How can i custom filter for 302 Status Code in spring mvc java and response.redirect to custom page?

Hi all I want to create RedirectionFilter at java spring. The main purpose is when status code 302 is detected then send redirect and replacing the response content by custom text content. The first problem is don't know how to catch the response code 302. This is my current thinking .
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) (request);
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
String redirectURL="www.google.com";
if(statuscode == 302 ){
httpServletResponse.sendRedirect(redirectURL);
}
Something like that. I have out of ideas. Thanks for helping.
You can use HandlerInterceptorAdapter to get the response after each call and can validate the response code and do necessary things
#Component
public class TestInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, java.lang.Object object) throws Exception {
System.out.println("test");
return true;
}
#Override
public void afterCompletion(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, java.lang.Object handler, #org.springframework.lang.Nullable java.lang.Exception ex) throws java.lang.Exception {
if(response.getStatus()==302){
// your code
}
}
}
After creating a interceptor need to register it in InterceptorRegistry
#Component
public class InterceptorsConfig implements WebMvcConfigurer {
#Autowired
private TestInterceptor testInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(testInterceptor);
}
}
Once triggering a request, the control will come to interceptor first.
Restcontroller sample
#RestController
#RequestMapping("/test")
public class Restcontroller {
#GetMapping
public ModelAndView redirectWithUsingRedirectPrefix(ModelMap model) {
model.addAttribute("attribute", "redirectWithRedirectPrefix");
return new ModelAndView("redirect:/redirectedUrl", model);
}
}

Spring #RequestMapping

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.

Spring 3 HandlerInterceptor passing information to Controller

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");
....
}

Restrict method on MultiActionController action

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)

Categories