DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Coding
  3. Java
  4. Once Roughhousers, Vaadin and Spring Security Can Finally Get Along

Once Roughhousers, Vaadin and Spring Security Can Finally Get Along

Nicolas Fränkel user avatar by
Nicolas Fränkel
CORE ·
Aug. 27, 12 · Interview
Like (0)
Save
Tweet
Share
5.16K Views

Join the DZone community and get the full member experience.

Join For Free

Along with Apache Shiro, Spring Security is one of the two most-used security components in the Java world. Using Spring Security with Vaadin needs a little work. In this article, I will show you how you can adapt your Vaadin application to play nice with Spring Security.

Credits go to Henri Sara of the Vaadin team who provided his valuable insight.
Requirements: this article assumes you know some Spring Security, and it uses advanced Vaadin navigator concept.

Nominal uses of Spring Security mandate for the use of subcontexts in the webapp. Each one can then be configured for different access levels. For example, /public is accessible with anonymous access, while /private needs some specific authorizations. Unfortunately, Vaadin doesn't work that way: views are translated into fragments, not subcontexts. From this point on, there are two options: Either tweak Vaadin to use subcontexts, or embed Spring Security inside our application. We will use the latter.

  • The first step is to create a Login form view that sends login events.
  • The root subscribes to login events and handles authentication attemps through a dedicated authentication handler.
  • The handler has to be passed to the login, the password and the http request. Since Vaadin hides the latter in the API, we have to create a special servlet that stores it in a thread local with the help of a utility class:
    public class RequestHolderApplicationServlet extends ApplicationServlet {
     
        @Override
        protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     
            RequestHolder.setRequest(request);
     
            super.service(request, response);
     
            // We remove the request from the thread local, there's no reason to keep it once the work is done
            RequestHolder.clean();
        }
    }
  • The login handler uses the Spring Security API to create the username/password token needed by the framework. Then it gets the authentication manager from the Spring context and calls the relevant method, delegating real authentication to the configured backend. Last but not least, we set authentication data into the Spring Security context for latter uses.
    public class AuthenticationService {
     
        public void handleAuthentication(String login, String password, HttpServletRequest httpRequest) {
             
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(login, password);
     
            token.setDetails(new WebAuthenticationDetails(httpRequest));
     
            ServletContext servletContext = httpRequest.getSession().getServletContext();
     
            WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
     
            AuthenticationManager authManager = wac.getBean(AuthenticationManager.class);
     
            Authentication authentication = authManager.authenticate(token);
     
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
    }
  • Don't forget to also create and clean the Spring Security context. Since we already developed a custom servlet, we'll update it.
    public class RequestHolderApplicationServlet extends ApplicationServlet {
     
        @Override
        protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     
            SecurityContextHolder.setContext(SecurityContextHolder.createEmptyContext());
     
            RequestHolder.setRequest(request);
     
            super.service(request, response);
     
            RequestHolder.clean();
     
            SecurityContextHolder.clearContext();
        }
    }
Now, the root just has to try/catch the authentication results and navigate to the desired view if succesful. Job complete!

But wait; what if the user knows about the view's name and types the fragment directly into his or her browser's URL bar? No login event, no authentication: he or she will have access directly to the main view, regardless of his or her credentials.

So, there's one last step to implement: we have to bind all our views into a navigator and let the latter handle navigation. Besides, we register it as a ViewChangeListener that will check for credentials before changing the view.

public class ViewChangeSecurityChecker implements ViewChangeListener {
 
    @Override
    public boolean isViewChangeAllowed(ViewChangeEvent event) {
 
        if (event.getNewView() instanceof LoginView) {
 
            return true;
        }
 
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
 
        return authentication == null ? false : authentication.isAuthenticated();
    }
 
    @Override
    public void navigatorViewChanged(ViewChangeEvent event) {}
}
Now, when an unauthenticated user directly types the view name as a fragment, there won't be any action. Notice that the login view has to be accessible in any case.

Note that the above code only checks for an authenticated status, not for a credential one. You can easily enhance it to do just that by forking the GitHub repo.

Original article: http://morevaadin.com/content/spring-security-integration

 

 

Spring Security Spring Framework Vaadin

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Why Every Fintech Company Needs DevOps
  • Visual Network Mapping Your K8s Clusters To Assess Performance
  • PostgreSQL: Bulk Loading Data With Node.js and Sequelize
  • How Do the Docker Client and Docker Servers Work?

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: