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. Frameworks
  4. Securing Your Website With Spring Boot

Securing Your Website With Spring Boot

Want to learn more about securing your website with Spring Boot? Check out this post about securing your webpage with just two Java classes and their HTML files.

Jesus J. Puente user avatar by
Jesus J. Puente
·
Oct. 30, 18 · Tutorial
Like (16)
Save
Tweet
Share
15.75K Views

Join the DZone community and get the full member experience.

Join For Free

In this post, I will explain how Spring manages security. I won't be covering everything, of course — the issue of security would be a big book, but we will at least take a look at how to secure a website.

As always, I want to start by saying that the source code can be found on my GitHub page. The program is made in Java using Spring Boot.

Well, let's start by look at how to secure a website in Spring.

Spring Boot is actually very simple because we will use what Spring calls starters, which are nothing but groups of packages grouped by the functions that they offer. So in this case, the package will include Web, Thymeleaf, and, of course, Security.

Here's a glimpse of Eclipse selecting the required packages.

Image title

As many of you already know, pom.xml file dependencies allow you to see more detail.

Thymeleaf is software that seamlessly integrates with Spring and creates webpage templates. This is similar to JSP, but Thymeleaf is a more improved version. Or, if you prefer JavaServer Faces, it would look more like JavaEE. The case is that it allows HTML pages to integrate seamlessly with our classes developed in Spring.

Since we want to see on our website, the username that we have recorded lets us use the library security Thymeleaf for Spring. To do this, we will include the following lines in our pom.xml file.

  <GroupId> org.thymeleaf.extras <groupId/>
   <ArtifactId> thymeleaf-extras-springsecurity4 <artifactId/>
    <Version> 3.0.3.RELEASE <version/>
<Dependency/>


And here, you can see how it will structure our program

Image title

Now, we begin declaring our first class, which I have called the WebSecurityConfiguration.java:

@SpringBootApplication
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

public static void main (String [] args) {
SpringApplication.run (WebSecurityConfiguration.class, args);
}

@Bean
@Override
public AuthenticationManager authenticationManagerBean () throws Exception {
       super.authenticationManagerBean return ();
}

    @Bean
    @Override
    public UserDetailsService userDetailsService () {

    UserDetails user = User.builder (). Username ( "user"). Password (passwordEncoder (). Encode ( "secret")).
    roles ( "USER") build ().;
    UserDetails UserAdmin = User.builder (). Username ( "admin"). Password (passwordEncoder (). Encode ( "secret")).
    roles ( "ADMIN") build ().;
        return new InMemoryUserDetailsManager (user, UserAdmin);
    }
    @Bean
    public PasswordEncoder passwordEncoder () {
        return new BCryptPasswordEncoder ();
    }

   @Override
    protected void set (http HttpSecurity) throws Exception {
        http
        .csrf (). disable ()
               .authorizeRequests ()
            .antMatchers ( "/" "/ index", "/ webpublico"). permitAll ()
            .antMatchers ( "/ webprivado"). authenticated ()
            .antMatchers ( "/ webadmin"). hasRole ( "ADMIN"). and ()
                .formLogin ()
                .loginPage ( "/ login")
                .permitAll ()
                .and ()
                .logout () // get method for I desabilitado CSRF
                .permitAll ();
    }
}


The first is to use labels @SpringBootApplication and @EnableWebSecurity. The first tag is obvious — since our application, we want to work with Spring Boot. The second is to specify that the web security is activated; honestly, this label is not required. Spring Boot is very clever, as we have seen package security (in the pom.xml, remember) in our project. It includes this message again, which is not necessarily a bad thing, as it provides further clarity but is, albeit, redundant.

Now, we specify that our class will inherit from theWebSecurityConfigurerAdapter because we will overwrite some of the functions of that class. So, you need to understand Spring and look to see if there is a class that implements the interfaceWebSecurityConfigurer, which implements the class  WebSecurityConfigurerAdapter, and if so, it uses the functions of that interface to configure the security application.

If we had a class that implements this interface, Spring simply would not access any page of our application, which, as you can probably understand, is not very practical.

Now, we need to write the function authenticationManagerBean to return the class responsible to manage authentications (as its name suggests). Okay, you might be wondering: but what about if you only call the function to define? This is actually very simple because we use the @Bean label for Spring. It is important to know where to get (injecting) the object type AuthenticationManager because you need to control security.

In the function userDetailsService, we define users who will have access to our website. In this case, we create two users: user and admin (yes, I know that I have not tried too hard choosing the names), each with its own password and role. Clarify that the ROLE is a free literal, meaning that this can be whatever you want. For example, USER_WITH_EYES — the fact is that then we will use that role, it must match letter by letter with the set.

Also, note that the password is encrypted, in this case, with the algorithm Bcrypt. We do this by calling the function passwordEncoder, which is annotated with the Spring@Bean label.

That is, Spring needs to know which encryption system we are using to store passwords, and it seeks an object that implements the interface PasswordEncoder. If we fail, we cannot find the application.

I want to clarify that we are using the simplest way to declare users and store them, in memory, with the class  InMemoryUserDetailsManager. In a real program, it would use JdbcUserDetailsManager, which would allow us to store them in a database. Or, this could include any other class that implements the interface  UserDetailsManager, as it could be LdapUserDetailsManager if we use an LDAP service.

And since we need to define which parts of our application will be protected, the roles must have permission to access every part of it. Yes, I have written roles and nonusers, because as we have said before, when you define a user, you must assign a role. And normally, the filtering rules are applied by the group to which the user belongs. To set permissions for each resource, we will configure the object HttpSecurity received in the function protected void configure (HttpSecurity http).

I'll explain line by line what is done in this function:

  •  csrf (). disable ()

First, we are looking at CSRF disable control. CRSF stands for Cross-site request forgery, as Wikipedia explains:

Cross-site request forgery, also known as one-click attack or session riding and abbreviated as CSRF (sometimes pronounced sea-surf) or XSRF, is a type of malicious exploit of a website where unauthorized commands are transmitted from a user that the web application trusts. There are many ways in which a malicious website can transmit such commands; specially-crafted image tags, hidden forms, and JavaScript XMLHttpRequests, for example, can all work without the user's interaction or even knowledge. Unlike cross-site scripting (XSS), which exploits the trust a user has for a particular site, CSRF exploits the trust that a site has in a user's browser.

Disabling the CRSF has the side effects that can perform a log out of a session with a request HTTP GET type, then default can only be done with a POST request:

  •  .authorizeRequests () .antMatchers ( "/" "/ index", "/ webpublico"). permitAll ()

We specify that the petitions on this route with any of the strings "/", "/ index", "/ webpublico" will not have security. That is be permitted for everyone.

  •  antMatchers ( "/webprivado"). authenticated () 

We specify that requests to the path "/webprivado" can only be processed if the user is authenticated, without specifying what role should belong.

  •  .antMatchers ( "/webadmin"). hasRole ( "ADMIN") 

Only users who are part of the group ADMIN will have access to the URL "/webadmin."

The function antMatchers allows the use of regular expressions, so if, for example, we would like to apply a rule to all that depends on a route, we could put this:

http.antMatchers ( "/ users /**"). hasRole ( "USER") to specify that any request to the URL /users /XXX only has access to users belonging to the group USER.

  •  .formLogin(). loginPage( "/login"). permitAll() 

We specify that the login page will be "/login" and allowed to reach everyone.

  •  logout(). permitAll() 

We specify the logout page should be allowed to reach everyone. By default, this page answers in the URL "/logout."

Perfect. We have defined the security of our websites. Now, we just define the entry points to the pages. This is done in the class WebController.java.

@Controller
public class WebController
{
 @RequestMapping ({ "/", "index"})
  public String start () {
    return "index";
  }

 @RequestMapping ( "/webprivado")
  public private String () {
    "Private" return;
  }
 @RequestMapping ( "/webpublico")
  public String loginpub () {
    "Public" return;
  }
 @RequestMapping ( "/webadmin")
  public String admin () {
    return "admin";
  }
 @RequestMapping ( "/login")
  public String login () {
    return "login";
  }
}


As seen above, a class has many mysteries. W simply specify the label @Controllerto be a class where we can define entry points for web requests.

We have different functions in the label @RequestMapping to specify the URL and be processed by each function. Thus, the function start will be called when a request to the URL, "/" or "/index." Note that we need to put in the initial bar.

The string returned will be the template that Thymeleaf returned so that the call start function will return the "index.html" template, as shown below:

<! DOCTYPE html>
<Html xmlns = "http://www.w3.org/1999/xhtml" xmlns: th = "http://www.thymeleaf.org"
      xmlns: sec = "http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
    <Head>
        <Title> Home Page </ title>
    </ Head>
    <Body>
   <H1> Home Page </ h1>
   <P> <a th:href="@{/webpublico}"> Click here to view a page </a> public. </ P>
   <P> If you are a regular user clicks </a> <a th:href="@{/webprivado}"> here to view a private page </ p>
   <P> If you are a regular administrator </a> click <a th:href="@{/webadmin}"> here to see the profile Administrator </ p>   
   <Div sec: Authorize = "isAuthenticated ()">
Hello <span sec: authentication = "name"> someone </ span>
<P> <a th:href="@{/logout}"> Disconnect </a> </ p>
</ Div>

    </ Body>
</ Html>


How does it look like pure HTML? This is one of the advantages of using Thymeleaf standard HTML tags. I will not explain the language here, but I will explain some of the labels used:

<a th:href="@{/webpublico}"> — Create a link to the URL "/webpublico." It would be like using the "tag <A href="/webpublico">.

<div sec: Authorize = "isAuthenticated ()"> —  This is the only code that will be rendered in the DIV if the user is authenticated. In other words, if the user is not logged in, it is not displayed on the web page that is between DIV tags (in fact, it will not show on the webpage or the DIV).

<span sec: authentication = "name"> someone </ span> —  If the user is logged in with their username, it will show what you have between tags span. In this case, it shows someone.

And with this, we have a secure application! Yep, we secure out a webpage with only two Java classes and their corresponding HTML files.

To finish this post, I leave some screenshots of the application:

Image title

This is the home page without having registered.

Image title This is the public page.

Image title

This looks at the home page once it has identified the 'user.'

Image title

Now, we are identifying the user "user:"

Image title

Now, we can see an error accessing the web page; " / admin" is registered with user 'user' and does not have permissions for that web page.


Hope this helps! Happy coding.

Spring Framework Spring Boot security application Requests

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Top 10 Secure Coding Practices Every Developer Should Know
  • Load Balancing Pattern
  • 5 Factors When Selecting a Database
  • OpenID Connect Flows

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: