I am working on a spring web socket app and I am looking to find a way to get hold of the spring web socket session decorator at my controller.
By looking at the spring code I saw that WebSocketSessions by default are decorated with ConcurrentWebSocketSessionDecorator in SubProtocolWebSocketHandler:decorateSession()
Here is how my code looks like
#Controller
public class MyController {
#MessageMapping("/endpoint")
public void method(Request request) {
//logic
// This is where I want to have access to ConcurrentWebSocketSessionDecorator
}
}
Is it possible to get access to the decorator in my controller ?
Thanks
Nikos
Related
I am using Jhipster(Angular + Springboot) Application for my existing project.
I managed to create a controller(app.resource) manually apart from the ones already generated by jhiptser(using .jh file) for achieving a file download functionality.
So, when we start the server we usually initiate two servers i.e gradlew and npm start. The second runs on port 9000 which eventually supports hot reload functionality.(front-end development)
So the problem is, I am able to access those endpoints from the server running on standard 8000 port. However, from the port which is a proxy(9000), the method is returning 404.
I tried to clean build the application several times.
NOTE: The #RequestMapping value on the new controller is different then those present already.
Does this have to do something with spring security?
Thanks in advance.
Here is the previous controller:
#RestController
#RequestMapping("/api")
public class FGAppDiagramResource {
#GetMapping(value = "/fg-app-diagram-downloadFile")
public void getImage(String fileName,String folderName, HttpServletResponse
response){
// Some Code
}
}
Here is my New controller:
#RestController
#RequestMapping("/fileDownload")
public class DownloadFileController {
private final Logger log =
LoggerFactory.getLogger(DownloadFileController.class);
public DownloadFileController() {
super();
}
#Autowired
private ApplicationProperties applicationProperties;
#GetMapping(value = "/fg-app-diagram-downloadFile/{fileName}/{folderName}")
public void getImage(#PathVariable String fileName,#PathVariable String folderName, HttpServletResponse response) {
// Some Code
}
}
Your new controller does not use /api so you must add your endpoint URL /fileDownload to proxy configuration of webpack dev server in webpack/webpack.dev.js
proxy: [{
context: [
/* jhipster-needle-add-entity-to-webpack - JHipster will add entity api paths here */
'/api',
'/fileDownload',
You may want to use /api/fileDownload to avoid changing proxy configuration and also because /api is useful for many other aspects like security and also using HTML5 URL routing strategy in Angular to get rid of # in client routes (see https://github.com/jhipster/generator-jhipster/pull/9098).
/api and /management are namespaces to avoid route conflicts, so it is usually wise to use them for your new endpoints.
Problem
I have set up a stomp websocket on spring, and have endpoints defined via the #MessageMapping annotation.
I had read that #PreAuthorize could be used to authorize on a per mapping basis but this doesn't appear to work. When using the #PreAuthorize, the request is not denied when the user is not in a specific role.
Code
#PreAuthorize("hasRole('ROLE_ADMIN')")
#MessageMapping(value="/addComment/{ID}")
public void addComment(#DestinationVariable Integer ID, String content, Principal principal)
throws Exception {
//Do stuff with ID,content etc
}
I currently have it set up like so
#Configuration
public class WebSocketSecurityConfig extends
AbstractSecurityWebSocketMessageBrokerConfigurer {
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.simpDestMatchers("/put/addComment/**").hasRole("ADMIN");
}
}
Although would prefer to annotate on each mapping since it is clearer for me.
Question(s)
Can preauthorize be used with mappings?
If so is there a reason that it is not working in the above example?
If not, is there a way to do this per mapping, instead of in the configurer?
Extra
Using Spring 4
Any more information needed let me know
Environment: JBoss AS 7, RestEasy 3.0.5.
I would like to use a preprocess filter in my application to authenticate a particular user and add this authenticated user to the request scope. I tried the following:
#Provider
public class SecurityFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) {
// authenticate, lookup user code etc...
requestContext.setProperty("User", new User("test"));
}
}
And then access it at the bean level using:
#Stateless
public class TestBean {
#Context HttpServletRequest servletRequest;
#GET
#Path("/hello")
public String hello() {
return "Hello " + servletRequest.getAttribute("User");
}
}
However the Context elements are not injected when the bean is annotated as stateless (stateless is required for EJB logic) due to a 2 year old RestEasy bug.
Can anyone think of a solution to this issue?
Alternatively, is there a more typical solution that prepopulating these objects using a filter?
Kind thanks for reading.
What I have done before is that I have a web application, "facade" if you want, to the EJBs. The JAX-RS layer is implemented in this application. A servlet filter intercepts the request to the JAX-RS resources and calls a CDI service that implements the "authenticate, lookup user code etc" logic. On success, the CDI service exports the current user object to CDI. This user object is #Inject'ed in the EJBs.
If CDI is an option for you (and I don't see why not in this setup), you could do the same (i.e. export the User to CDI) from your SecurityFilter, without having to create a web-app.
Additionally the dependency of the service layer (EJBs) to web-specific APIs (HttpServletRequest) is a bit creepy; I really think dependency injection of the actual User object is the way to go.
I'm using JBoss to provide a bunch of RESTful services to a Flex-based RIA. Anyway, I managed through some pain to realize a login (using form-based login) but I'm struggeling with providing a RESTful method to log the user out.
In a JSP I can simply call something like:
session.invalidate()
How can I do this with JBoss, Resteasy that uses stateless session beans to implement the RESTful services?
After a bit of googeling I created a solution:
This is the local interface of my RESTful service bean:
#Local
#Path("/Rest")
public interface SessionController {
...
#GET
#Path("/logout/")
#Produces("text/xml")
String logout(#Context HttpServletRequest req);
}
And this is the implementation:
#RolesAllowed({ "TheBoss", "SomeUser", ... })
#SecurityDomain("mysqlLogin")
#Stateless
public class SessionControllerBean implements SessionController {
...
public String logout(#Context HttpServletRequest req) {
...
req.getSession().invalidate();
return "SUCCESS";
}
}
Pretty simple as you can see. As I might have imagined already dependency injection is the trick. With the #Context annotation I can ask JBoss to inject the HTTPServletRequest from which I can get the session and call invalidate.
The bean is being called via resteasy as a RESTful service.
While developing with Java EE I find that I spend more time tracking down how to configure things in all these xml files (maven configuration is pure hell), which API's to use and how and which bean to inject than actually developing functionality.
I want the client and server application to talk to each other using REST services. I have been trying to design this using Spring MVC. I am looking for something like this:
Client does a POST rest service call saveEmployee(employeeDTO, companyDTO)
Server has a similar POST method in its controller saveEmployee(employeeDTO, companyDTO)
Can this be done using Spring MVC?
Yes, this can be done. Here's a simple example (with Spring annotations) of a RESTful Controller:
#Controller
#RequestMapping("/someresource")
public class SomeController
{
#Autowired SomeService someService;
#RequestMapping(value="/{id}", method=RequestMethod.GET)
public String getResource(Model model, #PathVariable Integer id)
{
//get resource via someService and return to view
}
#RequestMapping(method=RequestMethod.POST)
public String saveResource(Model model, SomeResource someREsource)
{
//store resource via someService and return to view
}
#RequestMapping(value="/{id}", method=RequestMethod.PUT)
public String modifyResource(Model model, #PathVariable Integer id, SomeResource someResource)
{
//update resource with given identifier and given data via someService and return to view
}
#RequestMapping(value="/{id}", method=RequestMethod.DELETE)
public String deleteResource(Model model, #PathVariable Integer id)
{
//delete resource with given identifier via someService and return to view
}
}
Note that there are multiple ways of handling the incoming data from http-request (#RequestParam, #RequestBody, automatic mapping of post-parameters to a bean etc.). For longer and probably better explanations and tutorials, try googling for something like 'rest spring mvc' (without quotes).
Usually the clientside (browser) -stuff is done with JavaScript and AJAX, I'm a server-backend programmer and don't know lots about JavaScript, but there are lots of libraries available to help with it, for example see jQuery
See also:
REST in Spring 3 MVC
Yes, Rest is very easy to implement using spring MVC.
#RequestMapping(value="/saveEmploee.do",method = RequestMethod.POST)
#ResponseBody
public void saveEmployee(#RequestBody Class myclass){
//saving class.
//your class should be sent as JSON and will be deserialized by jackson
//bean which should be present in your Spring xml.
}