So guys, there is a way to intercept urls, preventing non-logged users to acess, using spring security, but not at xml config or java based, something like #PreAuthorize on methods, and these ones return a view after they done something, but not like actions (add, delete).
Something like these:
#PreAuthorize("isAuthenticated")
#RequestMapping(value = "/home", method = RequestMethod.GET)
public String home()
{
return "home";
}
What you want to do is possible, but it's less performance efficient and scatters the security code all over the controllers. To see the full capabilities of Expression-Based Access Control, check out this documentation
Related
Recently I came accross this issue. Let's say that I want to give different authorizations to different methods within my controller. I would like to do this using the cookie that was send with the request and to do that I would like to use annotations. I tried to figure out how force #PreAuthorize annotation to work but I am missing something here.
Does anyone know if it's possible scenario (pseudo-code)
#Controller
class myController
{
#SomeAuthorizationAnnotation
#RequestMapping("/")
void doSth()
{
//something is done after authorization
}
}
And now i'd like to write my custom method which grants me access to http request sent to this controller where i could let's say write something like
HttpServletRequest ht = ....
Optional<Cookie> cookie = getCookie(ht.getCookies(), AUTH_TOKEN);
if (cookie.isPresent()) {
//grant authorization for the method call
}
I hope that this is somewhat understandable.
P.S I don't want to bind filters or sth to url's, i want to bind it to methods.
In way to secure your methods you can use #Secured or #PreAuthorize annotations but also you should declare it <global-method-security secured-annotations="enabled" />
See also method security
Well, my solution to this problem was by simply using Authentication Providers within Spring Security and implement interface of UserDetailsService to match my demands according to this project. So then my sessions are automatically handled without necessity for handling Cookies myself. And of course, annotations work.
I was wondering if there is a better way to handle handling sessions than running this set of code through each one of my controller methods.
public ModelAndView addUser(#RequestParam("userid") String userId,
#RequestParam("passwd") String passwd,
#RequestParam("usrtype") String usrtype,
HttpSession session,
Model model ){
ModelAndView mav = new ModelAndView();
if ((String) session.getAttribute("userId") == null) {
model.addAttribute("msg", "Session was terminated.");
model.addAttribute("url", "/login");
mav.setViewName("redirect");
return mav;
}
...
How would one go about making this into reusable code?
There are multiple ways to optimize this:
Securing requests is something Spring Security is made for. Spring Security uses a Servlet filter to intercept (and deny) requests before they arrive in your controller. So you do not have to handle security related code in controller actions
If, for whatever reason, you can/want not use Spring Security you should have a look at Spring's MVC interceptions. In interceptors you can place code that need to be executed before and after controller actions.
If you always need to set the same Model attribute you can annotate methods with #ModelAttribute. This method will then be called for every request to populate your model, see ModelAttribute methods documentation. ControllerAdvice is similar, it is used if other classes than the controller should provide model information.
Here I have to controller methods for example,
(Case 1) One way is
#Controller
#requestMapping("main")
Class ControllerClass{
#RequestMapping("first", method = RequestMethod.POST)
public String post(Model model){
//processing
return "redirect:second";
}
#RequestMapping("second", method = RequestMethod.GET)
public String post(Model model){
//processing
return "myview";
}
}
And (Case 2) another way is
#Controller
#requestMapping("main")
Class ControllerClass{
#RequestMapping("first", method = RequestMethod.POST)
public String post(Model model){
//processing
return "redirect:/main/second";
}
#RequestMapping("second", method = RequestMethod.GET)
public String post(Model model){
//processing
return "myview";
}
}
Both ways work correctly, but I want to know which one is better to avoid future problems like one I faced recently:
When I forwarded the request to /main/first from another controller, I got a 404 error in code which is using Case 1.
As per Spring Documentation:
The redirect: prefix
While the use of RedirectView works fine, if the controller itself creates the RedirectView, there is no avoiding the fact that the controller is aware that a redirection is happening. This is really suboptimal and couples things too tightly. The controller should not really care about how the response gets handled. In general it should operate only in terms of view names that have been injected into it.
The special redirect: prefix allows you to accomplish this. If a view name is returned that has the prefix redirect:, the UrlBasedViewResolver (and all subclasses) will recognize this as a special indication that a redirect is needed. The rest of the view name will be treated as the redirect URL.
The net effect is the same as if the controller had returned a RedirectView, but now the controller itself can simply operate in terms of logical view names. A logical view name such as redirect:/myapp/some/resource will redirect relative to the current Servlet context, while a name such as redirect:http://myhost.com/some/arbitrary/path will redirect to an absolute URL.
Most Real time enterprise project prefers to use case 2 in all controllers they use,so that the inter calling between different controller is fine.
To show the user's name on every Freemarker page, I could call model.addAttribute in every controller as below:
#RequestMapping(value = "index",method=RequestMethod.GET)
public String index(Model model) {
model.addAttribute("currentUser", App.getCurrentUser());
return "index";
}
#index.ftl
<div>${currentUser.userName}</div>
The calling would appear in everywhere of my code. It's really a nightmare. Is there any other way like AOP or Servlet Filter to set stuff into page?
You can use and interceptor for this, please check: http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-handlermapping-interceptor
This kind of information it would be better to keep it on a session scoped bean holding the user profile, rather than reloading it for every HTTP request.
This is the short description of my situation...
I have spring bean BookingServiceImpl which implements BookingService
BookingService has method: RoomDescription getRoomDescriptionById(String roomId);
I also have JSP page with javascript on it
I want to do something like this in javascript
var roomDescription = bookingService.getRoomDescriptionById(222);
/// ... use roomDescription
The question is: is there any existent framework which does things like that (magically allows to cal spring beans from javascript without additional boiler-plate code, assuming all parameters and method results are JSON-friendly)?
Spring provides mechanisms to expose RESTful endpoints via the Web MVC framework
The documentation is very good. A Controller definition for your specific example could look like this:
#Controller
#RequestMapping(value = "/rooms/{roomId}", method = RequestMethod.GET, produces="application/json")
#ResponseBody
public Room getRoom(#PathVariable String roomId, ModelMap modelMap) {
return bookingService.getRoomById(roomId);
}
On the javascript side, you could use jQuery to make an ajax call to retrieve the data. Here is an example of what that could look like:
$.getJSON('http://yourserver.com/rooms/222',
function(room) {
// Do something with room.description
});
This is a basic example (without proper error handling, security, etc). It's the closest thing to an existent framework that I'm aware of for Spring RESTful calls from javascript. If you need to access the Room data on the client side javascript then you'll need to expose it via some Spring construct (e.g. a Controller)
Take a look at DWR. This is as close as you will get to creating js clients.
http://directwebremoting.org/dwr/documentation/server/integration/spring.html