preface

Security is definitely important in Web application development, and Spring Security is a good choice to protect web applications. Spring Security is a Security module in the Spring project that makes it easy to integrate seamlessly with Spring projects. In particular, adding Spring Security to your Spring Boot project is easy. This article introduces Spring Security and its use in Web applications. Get started today with our first section of Getting started with Spring Security!

Let’s cut to the chase

Create an unprotected application

Suppose we have now created a SpringBoot Web application with a controller as follows:

@Controller
@RequestMapping("/sa")
public class HelloContoller {

 @RequestMapping("/hello")
 @ResponseBody
 public String test() {return "Hello ,spring security!"; }}Copy the code

As we can see, this is a simple SpringBoot project. Then we start the application, assuming that port is 8080, so when we visit http://localhost:8080/sa/hello in the browser can see Hello in the browser, spring security! .

We need to understand. This request is accessible to anyone. The next. We added Spring Security to protect the application

We added the Spring Security dependency to the POM file

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
</dependency>
Copy the code

Let’s log in again when they visit http://localhost:8080/sa/hello

This page is the default login page provided by Spring Security. Let’s log in. The default username is user, and if you’re careful, you’ll notice that the console prints a strange string of characters when you launch the app. Yes, that’s the password

We can also customize the user name and password instead of using what Spring Security provides us. We add the following code to the application.properties file

spring.security.user.name=admin
spring.security.user.password=admin
Copy the code

Here I have a custom user with both the username and password admin. Restart the project and you will notice that the console does not provide us with a random password. Then you use the username and password you set to log in will also be able to give you a message

Role-resource access control

In general, we need to implement “certain resources can only be accessed by certain roles”. Suppose our system has the following two roles:

ADMIN can access all resources

USER can only access specific resources

Now we add “/product” to the system to represent the product information resources (USER can access); Add resources for the /admin code administrator (not accessible to USER). The code is as follows:

@controller@requestMapping ("/admin")
public class AdminController {
    @RequestMapping("/info")
    @ResponseBody
    public String info() {return "Welcome to the admin page, you're the admin."; }}Copy the code
@controller@requestMapping ("/product")
public class ProductController {
    @RequestMapping("/info")
    @ResponseBody
    public String info() {return "Welcome back to the supplier page, where you are a regular user."; }}Copy the code

In a formal application, our users and roles are stored in a database; For the sake of this example, let’s create two users and roles that are stored in memory. We create SecurityConfiguration increase role user configuration class, this class inherits WebSecurityConfigurerAdapter classes, we rewrite the configure method here. The following code:

@ Configuration @ EnableWebSecurity public class SecurityConfiguration extends WebSecurityConfigurerAdapter {/ * in formal application, Our users and roles are stored in the database for easy demonstration. We create users and roles in the memory * / / / to create User User and Admin protected void the configure (AuthenticationManagerBuilder auth) throws the Exception { auth.inMemoryAuthentication() .withUser("yyw") // The administrator has admin and user permissions and can access all resources. Password ("123456"// Administrator password.roles("ADMIN"."USER") // Set admin and user permissions. And ().withuser ()"zs"// Common users can only access /product/**.password("123456"// Common user password.roles("USER"); Protected void configure(HttpSecurity HttpSecurity) throws Exception{ httpSecurity.authorizeRequests() .antMatchers("/product/**").hasRole("USER") // Assign accessible resources to the user role. AntMatchers ("/admin/**").hasRole("ADMIN"AnyRequest ().authenticated().and().formLogin().and().httpbasic (); }}Copy the code

Note that Spring Boot 2.0.3 references the security dependency of Spring Security 5.X. This version must provide an instance of PasswordEncorder, otherwise the background will report an error.

Therefore, you need to create an implementation class for PasswordEncorder. Here we define an MyPasswordEncoder

import org.springframework.security.crypto.password.PasswordEncoder;

public class MyPasswordEncoder implements PasswordEncoder {
    @Override
    public String encode(CharSequence charSequence) {
        return charSequence.toString();
    }

    @Override
    public boolean matches(CharSequence charSequence, String s) {
        returns.equals(charSequence.toString()); }}Copy the code

We then add this line to the Configure method of the SecurityConfiguration class we defined above

protected void configure(AuthenticationManagerBuilder auth) throws Exception{ Auth. InMemoryAuthentication (.) passwordEncoder (new MyPasswordEncoder ()) / / plus the withUser ("yyw") // The administrator has admin and user permissions and can access all resources. Password ("123456"// Administrator password.roles("ADMIN"."USER") // Set admin and user permissions. And ().withuser ()"zs"// Common users can only access /product/**.password("123456"// Common user password.roles("USER"); // Set user privileges}Copy the code

The following to verify that the average user login, restart the project, type http://localhost:8080/admin/info in your browser. Similarly, we will arrive at the login page, we enter username ZS, password is also 123456 result error page, denied access, message:

There was an unexpected error (type=Forbidden, status=403).
Access is denied
Copy the code

We changed the uri in the browser to: /product/info, and the access succeeded. You can see the welcome back to the supplier page, where you are a regular user. Zs can only access product/**, which is as expected.

To verify the administrator user login, after restart your browser, enter http://localhost:8080/admin/info. On the login page, enter the user name yyw and password 123456. After the submission, you can see the information, indicating that you can access administrator resources. Then we changed the browser URI to /product/info. After refreshing, we can also see the printed information, indicating that YYW users can access all resources, which is also consistent with our expectation.

Let’s recall that we did not add sa/ Hello to roles and permissions in HelloContoller. If we access sa/hello as admin, we’ll find that we can also return messages. If we switch back to user, we’ll find that we can also return messages. From this we draw a conclusion

As long as the request path is not configured in the following methods, anyone can access it. So let’s verify that. We configure requests for sa/** under the ADMIN role

protected void configure(HttpSecurity httpSecurity) throws Exception{
        httpSecurity.authorizeRequests()
                    .antMatchers("/product/**").hasRole("USER") // Assign accessible resources to the user role. AntMatchers ("/admin/**"."/sa/**").hasRole("ADMIN"AnyRequest ().authenticated().and().formLogin().and().httpbasic (); }Copy the code

We restart the project again. You will notice that only the admin user can access the hello request

We can also get information about the currently logged in user

Above we have achieved “resource – role” access control, the effect is consistent with our expectations, but not intuitive, we might as well try to get the “current login user” information in the controller, direct output, see the effect. Modify the sa/ Hello request method

@RequestMapping("/hello")
    public String test(){
        String currentUser = ""; // We get user information Object Principl = via SecurityContextHolder SecurityContextHolder.getContext().getAuthentication().getPrincipal();if(principl instanceof UserDetails) {
            currentUser = ((UserDetails)principl).getUsername();
        }else {
            currentUser = principl.toString();
        }
        return " some sa hello,currentUser is: "+currentUser;
    }
Copy the code

Starting the project, let’s revisit the Hello request and see that the page outputs user information

summary

At this point, we have a basic understanding of Spring Security. You learned how to add Spring Security to your project and how to control role access control for resources. Spring Security is more than that, and we’re just getting started. To better use Spring Security in the real world we need a deeper understanding. All right, let’s call it a day. See you next time!

The copyright of this article belongs to the code of swimming, please indicate the source. If the article is not enough, welcome to point, the follow-up will be improved.

If this article is helpful to you, please give me a like. Thank you very much!