John Dee.
John Dee.

Reputation: 11

Spring Security + Vaadin Session No VaadinSession

I a have working spring security project with vaadin session based on some github project. All is working fine until I create a new configuration static class where I want to specify the path where SSL should be required.

Here is my project and Application class in its original working state: https://github.com/czetus/dluznikApp/blob/master/src/main/java/com/danes/main/Application.java

Added code to Application.java into first static class

public static class SecurityConfiguriation extends GlobalMethodSecurityConfiguration

    @EnableWebSecurity
    public static class WebSecurity extends WebSecurityConfigurerAdapter{

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.requiresChannel()
                    .antMatchers("/v1*").requiresSecure();
        }


    }

The project is compiling and deploying wihtout any error. Problem starts when I start localhost:8080. I receive an exception defined here:

https://github.com/czetus/dluznikApp/blob/master/src/main/java/com/danes/main/servlet/VaadinSessionSecurityContextHolderStrategy.java .

java.lang.IllegalStateException: No VaadinSession bound to current thread
at com.danes.main.servlet.VaadinSessionSecurityContextHolderStrategy.getSession(VaadinSessionSecurityContextHolderStrategy.java:41) ~[classes/:na]
at com.danes.main.servlet.VaadinSessionSecurityContextHolderStrategy.clearContext(VaadinSessionSecurityContextHolderStrategy.java:12) ~[classes/:na]
at org.springframework.security.core.context.SecurityContextHolder.clearContext(SecurityContextHolder.java:73) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:180) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
...

If I remove annotation @EnableWebSecurity there is no error and ssl is not working.

When I was debugging I noticed that getSession is invoked too early in method

@Override
public void setContext(SecurityContext context) {
    getSession().setAttribute(SecurityContext.class, context);
}

in class VaadinSessionSecurityContextHolderStrategy.java

So what do I have to do or is there some other way to not create this configuration class and get this path (pattern) to be secured by SSL ?

Upvotes: 1

Views: 1533

Answers (1)

Mika
Mika

Reputation: 1276

Could you skip using VaadinSessionSecurityContextHolderStrategy? The default Spring security setup with thread local strategy should work.

Edit

Security context is typically stored in the thread that serves the request. Security filter is run before Vaadin servlet gets the request and this means that the session will not exist yet so the security filter cannot use Vaadin session to store the security context.

You can add relevant user data to Vaadin session with session init listener When it gets called the filter has already added user information to the thread local security context holder.

@Component("vaadinServlet")
@WebServlet(urlPatterns = "/*", name = "MyVaadinServlet", asyncSupported = true)
@VaadinServletConfiguration(ui = MyUi.class, productionMode = false)
public class MyVaadinServlet extends SpringVaadinServlet {
    private static final Logger logger = LoggerFactory.getLogger(MyVaadinServlet.class);

    @Override
    protected void servletInitialized() throws ServletException {
        getService().addSessionInitListener(this::onServletInit);
        super.servletInitialized();
    }

    private void onServletInit(SessionInitEvent sessionInitEvent) {
        SecurityContext securityContextOwnedByFilter = SecurityContextHolder.getContext();
        VaadinSession session = sessionInitEvent.getSession();
        User user = (User) securityContextOwnedByFilter.getAuthentication().getPrincipal();
        session.setAttribute("user", user);
        logger.info("User '{}' stored in session '{}'",
                user.getUsername(),
                session.getSession().getId());
    }
}

Upvotes: 1

Related Questions