Validation, exception handling, security etc. when using Spring Reactive WebFlux - spring-mvc

I was evaluating Spring Reactive WebFlux for a new project, and it looks quite interesting. But I'm unsure on how best to handle validation, security etc. For example, I'm used to having #Valid annotation in controllers for validating parameters, like this:
#PostMapping(value = "/users")
public User signup(#RequestBody #Valid UserCommand user) {
...
}
But now, when I now use a Mono<UserCommand> as the parameter, #Valid no more seems to work. Similarly, I guess other annotations like #JsonView, service method validation using #Validated, Spring Security annotations that refer to parameters (like #PreAuthorize("hasPermission(#user, 'edit')")) may not work with Mono<T> either. Do they?
Secondly, what about the #ControllerAdvices for catching exceptions? Would they work? What would be the best way to handle errors if they won't?

Related

Spring MVC - log every incoming http request call with payload into database

experts, I would log every incoming http request call with payload into database.
I checked there would be 2 approaches.
use filter or interceptor.
I feel filter is so easier for me to implement.
what would be best approach for my purpose?
please kindly advise.
thank you very much!
if you have a need to do something completely generic (e.g. log all requests), then a filter is sufficient - but if the behavior depends on the target handler or you want to do something between the request handling and view rendering, then the HandlerInterceptor provides that flexibility.
But anyway, just do the way which make you feel easily and simply.
Note:
Interceptor work in spring application context
Servlet work in web context
Use Spring AOP. Use any advice according to your needs.
#Aspect
#Component
public class Test {
#Around("#annotation(mapping) ")
public Object preAuthUserPersmission(ProceedingJoinPoint joinPoint, RequestMapping mapping) throws Throwable {
Object[] parameters = joinPoint.getArgs();
// Your actions on the input parameters
return joinPoint.proceed(joinPoint.getArgs());
}
}

How to access "session" scoped beans in a Spring WebSocket handler (not "websocket" scope)

In a raw Spring WebSocket application (not using sockjs/STOMP or any other middleware), how can I have Spring inject beans that have been registered in the HTTP session scope so that they can be used by code in my WebSocketHandler bean?
Note that what I am not asking is any of these questions:
How do I create beans in a scope that is accessible to all handler invocations for the same WebSocket session (e.g. as described in the answer to Request or Session scope in Spring Websocket). The beans I need to access already exist in the scope for the HTTP session
How do I (programatically) access objects in the servlet container's HTTP session storage (I haven't tried to do this, but I'm pretty sure the answer involves using an HttpSessionHandshakeInterceptor), but that doesn't get me injection of Spring scoped dependencies.
How to use a ScopedProxy to pass beans between code in different scopes (e.g. as described here); I'm already familiar with how to do this, but attempting to do so for a WebSocketHandler causes an error because the session scope hasn't been bound to the thread at the point the object is accessed.
How to access the current security principal -- again, very useful, but not what I'm currently trying to achieve.
What I'm hoping to do is provide a simple framework that allows for the traditional HTTP-request initiated parts of an MVC application to communicate directly with a WebSocket protocol (for sending simple push updates to the client). What I want to be able to do is push data into a session scoped object from the MVC controller and pull it out in the websocket handler. I would like the simplest possible API for this from the MVC controller's perspective, which if it is possible to just use a session-scoped bean for this would be ideal. If you have any other ideas about very simple ways of sharing this data, I'd also like to hear those in case this approach isn't possible.
You can also use Java API for websocket. This link https://spring.io/blog/2013/05/23/spring-framework-4-0-m1-websocket-support
explains how to do this with Spring.
Ufortunately, something like this
#ServerEndpoint(value = "/sample", configurator = SpringConfigurator.class)
public class SampleEndpoint {
private SessionScopedBean sessionScopedBean;
#Autowired
public SampleEndpoint(SessionScopedBean sessionScopedBean) {
this.sessionScopedBean = sessionScopedBean;
}
}
causes exception (because we're trying to access bean outside its scope), but for singleton and prototype beans it works well.
To work with session attributes you can modify the hanshake and pass required attributes:
public class CustomWebSocketConfigurator extends SpringConfigurator {
#Override
public void modifyHandshake(ServerEndpointConfig config,
HandshakeRequest request,
HandshakeResponse response) {
//put attributes from http session to websocket session
HttpSession httpSession = (HttpSession) request.getHttpSession();
config.getUserProperties().put("some_attribute",
httpSession.getAttribute("some_attribute_in_http_session"));
}
}
P. S. More a comment than an answer. I just wanted to add another way of handling session attributes in websocket to your question-answer. I have been searching the web for exactly the same issue and the way showed above seems to me the most systematic approach to handling the session data in websocket.

How to Set Request Headers Using a Feign Client?

We are developing a suite of Microservices using Spring Cloud framework and one of the the things that we need to do is to set request headers. I know I can pass a parameter #RequestHeader to a Feign method but the value needs to come from another bean. I don't know if SPEL can be used for a Feign param value.
I was thinking that this is a common enough use case for most clients so there'd be some examples, but so far I've not found any. Of course I can dig through the Spring course code and try to override the default Feign configuration but it kinda defeats the purpose of a declarative client if I've to write a lot of code to achieve this.
Any thoughts?
I have done this before using a RequestInterceptor as follows:
#Component
public class MyRequestInterceptor implements RequestInterceptor {
#Override
public void apply(RequestTemplate template) {
template.headers(getHeadersFromWherever());
}
}
You can find some more useful information here:
https://github.com/Netflix/feign#user-content-setting-headers-per-target

Handle cookie in Spring MVC

I have an Spring MVC application which using the classic three layer: controller service and dao.
And the related models in the application contains User Department Project.
One user will belong to a department, and there may be a lot of projects belong to a certain department, and the departments are organized as a tree like structure, for example:
dep1
dep1-1
dep1-1-1
dep1-1-2
...
...
...
Now I have a controller to list the projects:
class ProjectController{
private ProjectService projectService;
#RequestMapping("/list")
public String list(#RequestParameter("depId") String depId){
projectService.list(depId);
return "list";
}
}
ProjectServiceImpl implements ProjectService{
ProjectDao projectDao;
public List<Department> list(String depId){
}
}
It seems that this is rather simple, however we have two problems:
1 The result filter.
According to the configuration, the department of the current user maybe(or not) be under consideration during the query operation, for example, when the parameter depId is dep1-1-1, and the current user belongs to dep1-1-2, then we should return null.
As said, this feature maybe closed at all at some situation.
2 The authentication.
The user authentication and management is served in another application which will deployed at the same domain with my application, you can think they are two different folder inside the /tomcat/webapps. We use cookie to share the user information:save a token for a user.
Which means for every request, I will have to get the token of the current user(if they have login) from the cookie, and then call the service provided by the other application to get the information like department and etc.
So where to do the department check, in controller or service? I am not sure if inject the HttpRequest to service is a good idea or not.
Also Since there are too many controllers and services related to this kind of operation, I want to avoid the duplicate codes everywhere.
Is there any better choices?
It may be overkill, but what you are asking for make me think to spring-security :
authentication : spring security could do it directly, but you can also implement a custom PreauthenticatedAuthenticationFilter that would use the cookie to get the user info and populates a Spring Security Authentication token. This part is easy and highly configurable.
result filter : extract from the spring security reference manual :
Spring Security supports filtering of collections and arrays and this can now be achieved using expressions. This is most commonly performed on the return value of a method. For example:
#PreAuthorize("hasRole('ROLE_USER')")
#PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
public List<Contact> getAll();
When using the #PostFilter annotation, Spring Security iterates through the returned collection and removes any elements for which the supplied expression is false
All this is implemented through Spring AOP so it is easy to add those annotations on service methods.
Spring Security integrates nicely in a Spring MVC application. The only problem is that a full configuration including domain object security is not really trivial ...

Can I let some function executed before any controller in spring mvc

I use spring mvc 3.0, in our system there are some object like current user will be used in controller and in page. Now, in all function, I always get user from spring security context, and set it into ModelMap, then it can be got in page. And in most of the function, the user object will also be got from ModelMap and used as some parameters.
I want to know that, except interceptor, is there some way that I can set these objects into ModelMap before any function?
And in interceptor, I can only set into request, but actually, some data are already in servlet context.
Thanks.
Try for this a annotation style as #PreHandle with this can be annotated your method or function,
and means that Handler invoke execution of this function/method right before Dispatcher handle appropriate controller.
exact explain can be found here: http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/web/servlet/HandlerInterceptor.html

Resources