Vaadin #Push with Vaadin4Spring Security - spring-boot

Is anyone using Vaadin #Push with vaadin-spring-boot-starter and Vaadin4Spring Security extension?
Here is Vaadin related dependencies on our project:
compile 'com.vaadin:vaadin-client-compiled:7.5.8'
compile 'com.vaadin:vaadin-client:7.5.8'
compile 'com.vaadin:vaadin-themes:7.5.8'
compile 'com.vaadin:vaadin-server:7.5.8'
compile 'com.vaadin:vaadin-push:7.5.8'
// Official VaadinSpring Integration
compile("com.vaadin:vaadin-spring-boot-starter:1.0.0")
//Vaadin extentions - in the future more of those will go to official VaadinSpring Integration
compile("org.vaadin.spring.extensions:vaadin-spring-ext-security:0.0.6.RELEASE")
compile("org.vaadin.spring.extensions:vaadin-spring-ext-core:0.0.6.RELEASE")
compile("org.vaadin.spring.extensions:vaadin-spring-ext-boot:0.0.6.RELEASE")
compile("org.vaadin.spring.extensions:vaadin-spring-ext-test:0.0.6.RELEASE")
Here is the annotations on UI Class
#Theme("mytheme")
#Title(com.test.util.Constants.TITLE)
#EnableOAuth2Client
#SpringUI
#Push
public class MyVaadinUI extends UI {
...
}
And, Application.java ;
#EnableVaadinExtensions
#SpringBootApplication
#EnableConfigurationProperties
#EnableI18N
#EnableEventBus
#RestController
#EnableOAuth2Client
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
#Bean
public RequestContextListener requestContextListener(){
return new RequestContextListener();
}
#Bean
public FilterRegistrationBean hiddenHttpMethodFilter() {
HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(hiddenHttpMethodFilter);
return registrationBean;
}
#Bean(name = "messageSource")
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages/messages");
logger.debug("Returning messageSource: " + ((messageSource != null) ? messageSource.toString() : "NULL"));
return messageSource;
}
}
As soon as we call
security.login(username.getValue(), password.getValue());
(security is org.vaadin.spring.security.VaadinSecurity;)
we get the below exception;
16:36:35.272 [http-nio-8080-exec-9] ERROR c.b.g.c.s.v.views.login.LoginBox/login Login ERROR occured during login.org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.httpService': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
I appreciate any help you can provide.

You are using Websockets, which do not use servlet requests and will not activate the "request" scope automatically.
If you use #Push(transport=WEBSOCKET_XHR) it should work, as the websockets channel will then be used only for server -> client pushes and standard HTTP requests will be used for client -> server messages.

Related

Camel REST and Spring Security Java Configuration

I'm trying to set up Camel REST to use basic auth with a simple username/password from my application.properties and can't for the life of me seem to configure Camel Spring Security to do that. I'm trying to follow the Spring Security component documentation which seems to be missing the example of configuring the required beans. I found the missing example here under 'Controlling access to Camel routes' but this only shows the xml configuration.
How do I set up the required SpringSecurityAuthorizationPolicy bean? It needs an AuthenticationManager and an AccessDecisionManager and it also seems to require that I set its SpringSecurityAccessPolicy which I have no idea how to do.
I haven't gotten to test these yet, because I can't get my beans set up, but my rest route looks like:
rest("/ingest")
.post("/json").consumes("application/json")
.route()
.process(authProcessor)
.policy(authPolicy) // this is the bean I don't know how to configure
.to("direct:ingest")
.endRest();
and my AuthProcessor (taken from the camel component doc) looks like:
#Component
public class AuthProcessor implements Processor {
public void process(Exchange exchange) {
String userpass = new String(Base64.decodeBase64(exchange.getIn().getHeader("Authorization", String.class)));
String[] tokens = userpass.split(":");
// create an Authentication object
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(tokens[0], tokens[1]);
// wrap it in a Subject
Subject subject = new Subject();
subject.getPrincipals().add(authToken);
// place the Subject in the In message
exchange.getIn().setHeader(Exchange.AUTHENTICATION, subject);
}
}
and here's my broken bean configuration for what it's worth:
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
public SpringSecurityAuthorizationPolicy springSecurityAuthorizationPolicy(
AuthenticationManager authenticationManager, AccessDecisionManager accessDecisionManager) {
SpringSecurityAuthorizationPolicy policy = new SpringSecurityAuthorizationPolicy();
SpringSecurityAccessPolicy springSecurityAccessPolicy = new SpringSecurityAccessPolicy();
policy.setAuthenticationManager(authenticationManager);
policy.setAccessDecisionManager(accessDecisionManager);
policy.setSpringSecurityAccessPolicy(????);
return policy;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("pass").roles("USER");
}
#Bean(name = BeanIds.AUTHENTICATION_MANAGER)
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public AccessDecisionManager accessDecisionManager() {
AffirmativeBased affirmativeBased = new AffirmativeBased(ImmutableList.of(
new RoleVoter()
));
affirmativeBased.setAllowIfAllAbstainDecisions(true);
return affirmativeBased;
}
}
I've been banging my head against the wall trying to understand this so an example of how to do this would be amazing. It looks like the xml configuration for what I want to do (in the second link) is simple enough but I can't seem to replicate it in Java configuration.
I know it's an old topic, but I ran into similar questions. I managed to get it working. Not by overriding the accessDecisionManager() method within the WebSecurityConfigurerAdapter class, but by constructing a new instance while building my SpringSecurityAuthorizationPolicy:
#Bean
public Policy adminPolicy(AuthenticationManager authenticationManager) {
RoleVoter roleVoter = new RoleVoter();
SpringSecurityAuthorizationPolicy policy = new SpringSecurityAuthorizationPolicy();
policy.setAuthenticationManager(authenticationManager);
policy.setAccessDecisionManager(new UnanimousBased(List.of(roleVoter)));
policy.setSpringSecurityAccessPolicy(new SpringSecurityAccessPolicy(roleVoter.getRolePrefix() + "<ROLE_NAME>");
return policy;
}

Manual configuration of global exception handler in spring webflux through httpHandler bean

I am developing a set of reusable stuff like filters, global exception handlers and other spring webflux components, that would be used by reactive spring apps (webflux)
Since, this is a library (a jar), that will be consumed by apps, I dont want to annotate the global exception handler class with #Configuration and instead would like to let the applications programmatically configure the exception handler as needed. I see from the docs, that the way to configure the WebExceptionHandler is through the HttpHandler.
#Component
#AllArgsConstructor
public class TestApplicationConfig {
private ApplicationContext applicationContext;
#Bean
public HttpHandler routeHandler() {
return WebHttpHandlerBuilder.applicationContext(applicationContext)
.exceptionHandler(new ServiceExceptionHandler())
.build();
}
}
//exception handler
#NoArgsConstructor
#Order(-2)
#Slf4j
public class ServiceExceptionHandler implements ErrorWebExceptionHandler {
#SuppressWarnings("NullableProblems")
#Override
public Mono<Void> handle(ServerWebExchange serverWebExchange, Throwable err) {
}
}
The routeHandler bean gets called by the framework, but the exception handler is not called for any exception. If I have #Configuration in the exception handler class, then it is getting called. Wondering if I making a mistake in the way I am exposing the HttpHandler as a bean

In the configuration there is an error about DispatcherServletPath

Error output, error occurs when the application starts and in the version spring-boot-starter-parent 2.0.5.RELEASE, in 1.5 versions it works fine. In versions 2.0.5 the distribution of the SpringBootServletInitializer file has changed;
Dependency annotations: {}
19:03:05.312 [main] ERROR o.s.b.d.LoggingFailureAnalysisReporter -
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 1 of constructor in
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration required a bean of type 'org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath' that could not be found.
- Bean method 'dispatcherServletRegistration' not loaded because DispatcherServlet Registration found servlet registration bean dispatcherServletRegistration
Action:
Consider revisiting the entries above or defining a bean of type 'org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath' in your configuration.
Configuration:
#SpringBootApplication
#Import({
CityContextConfig.class,
CityPersistenceJpaConfig.class,
CityServiceConfig.class,
CityWebConfig.class
})
public class CityApp extends SpringBootServletInitializer {
#Bean
public DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}
#Bean
public ServletRegistrationBean dispatcherServletRegistration() {
final ServletRegistrationBean registration = new ServletRegistrationBean<>(dispatcherServlet(), "/api/*");
final Map<String, String> params = new HashMap<String, String>();
params.put("contextClass", "org.springframework.web.context.support.AnnotationConfigWebApplicationContext");
params.put("contextConfigLocation", "org.spring.sec2.spring");
params.put("dispatchOptionsRequest", "true");
registration.setInitParameters(params);
registration.setLoadOnStartup(1);
return registration;
}
//
#Override
protected SpringApplicationBuilder configure(final SpringApplicationBuilder application) {
return application.initializers(new MyApplicationContextInitializer()).sources(CityApp.class);
}
public static void main(final String... args) {
new SpringApplicationBuilder(CityApp.class).initializers(new MyApplicationContextInitializer()).listeners().run(args);
}
}
The project structure is divided into two modules common and webapp
A bit old, but for the record, you can fix it quickly just adding next bean:
#Bean
public DispatcherServletRegistrationBean dispatcherServletRegistrationBean() {
return new DispatcherServletRegistrationBean(dispatcherServlet(), "/");
}
Servlet context path has been changed in 2.x
here are my recommendation which should work
define servlet context path in application.properties.
server.servlet.path=/ # Path of the main dispatcher servlet.
make sure you have #Configuration notation on these configuration classes CityContextConfig.class, CityPersistenceJpaConfig.class, CityServiceConfig.class, CityWebConfig.class
#SpringBootApplication
public class CityApp {
#Override
protected SpringApplicationBuilder configure(final SpringApplicationBuilder application) {
return application.initializers(new MyApplicationContextInitializer()).sources(CityApp.class);
}
public static void main(final String... args) {
new SpringApplicationBuilder(CityApp.class).initializers(new MyApplicationContextInitializer()).listeners().run(args);
}
}
I am also searching for the answer. There is a migration guide from spring 1.5.x to 2.0. here Migration Guide
I think our solution is that. But I dont know how to implement their suggestion.

SpringBoot HandlerInterceptor not intercepting library endpoint

I have a SpringBoot app where I have implemented a HandlerInterceptor to log general information about API usage. I want it to also log requests to Spring Security's OAuth2 endpoint but it does not intercept the request.
#Configuration
public class WebConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addInterceptors(InterceptorRegistry registry) {
// register the interceptor that will write API usage info to a file
registry.addInterceptor(new ServiceUsageInterceptor());
}
How can I configure the HandlerInterceptor to intercept all requests?
Thanks
This turned out to be unrelated to the interceptor. The usage was being written to a log file using a custom AccessLogValve in the embedded Tomcat. Updating the pattern seemed to resolve the issue.
#Override
public void customize(ConfigurableEmbeddedServletContainer container) {
TomcatEmbeddedServletContainerFactory factory = (TomcatEmbeddedServletContainerFactory) container;
CustomAccessLogValve accessLogValve = new CustomAccessLogValve();
accessLogValve.setEnabled(true);
// set pattern
accessLogValve.setPattern("timestamp=\"%t\" local_host=\"%v\" status=\"%s\" remote_host=\"%h\" client_id=\"%q\" uri=\"%r\" execution_time=\"%D\"");
factory.addContextValves(accessLogValve);
}
}

How to migrate from AnnotationMethodHandlerAdapter to RequestMappingHandlerAdapter

I'm building REST services via Spring MVC in the application where the GUI is managed by Wicket. Basically, all I need is the DispatcherServlet and a controller with #RequestMapping/#RequestBody.
Because services serve JSON, I need to set MappingJackson2HttpMessageConverter. I can do this via AnnotationMethodHandlerAdapter and that works fine:
#Configuration
#ComponentScan("cz.swsamuraj.wicketspring")
public class SpringRestConfiguration {
#Bean
public AnnotationMethodHandlerAdapter annotationMethodHandlerAdapter() {
HttpMessageConverter<?>[] converters = { new MappingJackson2HttpMessageConverter()};
AnnotationMethodHandlerAdapter adapter = new AnnotationMethodHandlerAdapter();
adapter.setMessageConverters(converters);
return adapter;
}
}
The problem is that AnnotationMethodHandlerAdapter is deprecated and it's recommended to use RequestMappingHandlerAdapter instead.
But if I use this configuration:
#Configuration
#ComponentScan("cz.swsamuraj.wicketspring")
public class SpringRestConfiguration {
#Bean
public RequestMappingHandlerAdapter requestHandler() {
RequestMappingHandlerAdapter adapter = new RequestMappingHandlerAdapter();
adapter.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
return adapter;
}
}
I receive an exception:
javax.servlet.ServletException: No adapter for handler [cz.swsamuraj.wicketspring.ws.api.QuestionApiController#69f8a79f]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler
at org.springframework.web.servlet.DispatcherServlet.getHandlerAdapter(DispatcherServlet.java:1198)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
So, my question is: how can I set up a handler adapter in the RequestMappingHandlerAdapter?
I spent couple of days of research, but I didn't find any useful example of how to configure RequestMappingHandlerAdapter. All the advices just says to put #EnableWebMvc on the configuration, but this is not the way because of this Wicket-Spring coexistence.
Just to provide a full context, I've created a small buildable and runnable project on Bitbucket: sw-samuraj/blog-wicket-spring-rest
I was able to solve my problem with different approach - with usage of WebApplicationInitializer, I was able to put the #EnableWebMvc annotation on my configuration class and therefore neither the bean RequestMappingHandlerAdapter, nor AnnotationMethodHandlerAdapter are necessary. JSON now works fine, out-of-the-box.
Configuration
#Configuration
#EnableWebMvc
#ComponentScan("cz.swsamuraj.wicketspring")
public class SpringRestConfiguration {
// some additional beans needed for business logic
}
WebApplicationInitializer
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.register(SpringRestConfiguration.class);
servletContext.addListener(new ContextLoaderListener(dispatcherContext));
ServletRegistration.Dynamic dispatcher =
servletContext.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/rest/*");
}
}
Example project
Complete working example is on Bitbucket: blog-wicket-spring-rest

Resources