Spring Security: 1 [Overview of Permission Management, Spring Security Authentication and Authorization]


Spring Security

learning target

  • Understand rights management concepts
  • What problems can be solved by mastering SpringSecurity and why should we learn it?
  • Master how to authenticate with Spring Security
  • Master how Spring Security does authorization
  • Understand the underlying principles of authentication and authorization
  • Master integrating authentication and authorization in projects
  • Master JWT

1. Overview of rights management

Permission management generally means that according to the security rules or security policies set by the system, users can access and can only access the resources they are authorized to. Permission management appears in almost any system, as long as there is a system with users and passwords. Many people often confuse concepts such as "user identity authentication", "password encryption" and "system management" with the concept of rights management.

1.1.What is certification

Entering the era of mobile Internet, everyone uses their mobile phones every day. Commonly used software include WeChat, Alipay, Toutiao, etc. Let’s take WeChat as an example to illustrate the basic concepts related to authentication. Before using WeChat for the first time, you need to register as a WeChat user and enter your account number. and password to log in to WeChat. The process of logging in to WeChat by entering your account number and password is authentication.

Why does the system need to be authenticated?

Authentication is to protect the privacy data and resources of the system. Only users with legal identities can access the resources of the system.

1.2 What is authorization?

There are many resources in a platform. Different users can operate different resources and need to be granted different permissions. Only when they are granted can they operate. This is authorization.

Why authorize?

Authentication is to ensure the legitimacy of the user's identity, and authorization is to divide private data in a more fine-grained manner. Authorization occurs after the authentication is passed, and controls different users' ability to access different resources.

1.3 Authorized data model RBAC

Role Based Access Control (RBAC) in functional rights management is most commonly used in rights management.

Insert image description here

When we need to use permission management in a project, we can choose to implement it ourselves (the RBAC system implemented in the previous course), or we can choose to use a third-party implemented framework to implement it. Which one of them is better depends on Everyone has specific needs in the project.

Necessary functions to implement the rights management system:

1.权限管理(自定义权限注解/加载权限)
2.角色管理(新增/编辑/删除/关联权限)
3.用户管理(新增/编辑/删除/关联用户)
4.登录功能(定义登录拦截器/登录逻辑实现/登出功能)
5.权限拦截(定义权限拦截器/拦截逻辑实现)
1.3.1 Role-based access control

RBAC role-based access control (Role-Based Access Control) is authorized by role. For example, if the subject's role is general manager, he can query enterprise operation reports, query employee salary information, etc. The access control process is as follows:

Insert image description here

According to the judgment logic in the above figure, the authorization code can be expressed as follows:

if(主体.hasRole("总经理角色id")){
    
    
查询工资
}

If the roles required for salary query in the above figure change to general manager and department manager, then the judgment logic needs to be modified to "determine whether the user's role is general manager or department manager". The modified code is as follows:

if(主体.hasRole("总经理角色id") || 主体.hasRole("部门经理角色id")){
    
    
查询工资
}

According to the above example, it is found that when the permissions of a role need to be modified, the authorization-related code needs to be modified, and the system scalability is poor.

1.3.2 Resource-based access control

RBAC resource-based access control (Resource-Based Access Control) is authorized based on resources (or permissions). For example, users must have salary query permission before they can query employee salary information, etc. The access control process is as follows:

Insert image description here

Based on the judgment in the above figure, the authorization code can be expressed as:

if(主体.hasPermission("查询工资权限标识")){
    
    
查询工资
}

Advantages: The permission identification for salary query is defined when the system is designed. Even if the roles required for salary query change to general manager and department manager, there is no need to modify the authorization code, and the system is highly scalable.

1.4 Rights management framework

What problems can the framework help us solve in the rights management system?

Function What the permissions framework can do
authority management ×
role management ×
User Management ×
Login function √ (Password encryption, verification code, remember me)
Permission interception √ (Built-in many interceptors, providing tags/annotations/programming methods for permission authentication)

Here we introduce two commonly used rights management frameworks:

1.4.1 Apache Shiro

Apache Shiro is a powerful and easy-to-use Java security framework. More and more people are using Apache Shiro. It can implement functions such as authentication, authorization, password and session management.

1.4.2 Spring Security

Spring Security is also a popular security rights management framework, and it is closely integrated with Spring.

1.4.3 Comparison between Shiro and Spring Security

The biggest difference between Shiro and spring security is that shiro is an independent module, which is flexible to use, but will result in intrusive design; while spring security relies on spring's filter proxy mechanism and is bound to spring, which is not flexible enough, but is not intrusive. of. In addition, both shiro and spring security support password encryption, shiro supports session management, and spring security provides protection against common vulnerabilities (such as CSRF)

2. Spring Security authentication and authorization

Spring Security is a security framework that provides declarative security access control solutions for Spring-based enterprise application systems. Because it is a member of the Spring ecosystem, it is constantly revised and upgraded along with the entire Spring ecosystem. It is very simple to add Spring security to the Spring boot project. Using Spring Security reduces the need to write a lot of duplicate code for enterprise system security control. work.

2.1 Environment preparation

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <!--spring security 组件-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!--web 组件-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- test 组件-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
    </dependencies>

Create application.properties and startup classes

Startup class

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

CreateController

@RestController
public class HelloController {
    
    
    @RequestMapping("/hello")
    public String hello(String name){
    
    
        return "操作成功";
    }
}

Start the project:
The observation console will generate a password. The default account is user.

Using generated security password: a6c875c9-9b2e-4df9-a517-56c571258b01

Access resources in the browser: http://localhost:8080/hello?name=zhangsan, you will find that access to resources is blocked. SpringSecurity provides an authentication page by default, and no additional development is required.

2.2 Certification

2.2.1 Security configuration

Spring security provides username and password login, logout, session management and other authentication functions, which only need to be configured to use.
Define WebSecurityConfig under the config package. Security configuration includes: user information, password encoder, and security interception mechanism.

@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    
    
//配置用户信息服务
    @Bean
    public UserDetailsService userDetailsService() {
    
    
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("zhangsan").password("123").authorities("p1").build());
        manager.createUser(User.withUsername("lisi").password("456").authorities("p2").build());
        return manager;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
    
    
        return NoOpPasswordEncoder.getInstance();
    }

    //配置安全拦截机制
    protected void configure(HttpSecurity http) throws Exception {
    
    
        http
                //配置权限
                .authorizeRequests()
                .antMatchers("/hello").permitAll()
                .anyRequest().authenticated()
         http.formLogin()
                //登录成功后调整页面
                successForwardUrl("/main");
    }
}

controller:

@RequestMapping("/main")
public String main(String name){
    
    
    return "redirect:/main.html";
}

main.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
我是主界面
</body>
</html>

In the userDetailsService() method, we return a UserDetailsService to the spring container, which Spring Security will use to obtain user information. We temporarily use the InMemoryUserDetailsManager implementation class, and create two users, zhangsan and lisi, respectively
, and set passwords and permissions.

In configure(), we set up security interception rules through HttpSecurity, which include the following:
(1) The resource of url matching /hello is allowed.
(2) Other URLs require authentication.
(3) Enable form submission authentication. Successful login will jump to the /main path.

2.2.2 Customized login interface

Create a login interface in static

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org/" lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户登录</title>
</head>
<body>
<h1>用户登录</h1>
<form action="/login" method="post">
    用户名:<input type="text" name="username"> <br>
    密码:<input type="text" name="password"><br>
    <input type="submit" value="登录">
</form>
</body>
</html>

Add to configuration class:

 protected void configure(HttpSecurity http) throws Exception {
    
    
        http
                //配置权限
                .authorizeRequests()
                .antMatchers("/hello").authenticated()
                .anyRequest().permitAll()
           .and()
                //配置表单登录
                .formLogin().
                    loginPage("/login.html"). 
                    loginProcessingUrl("/login").
                    successForwardUrl("/main");
    }

In configure(), we set up security interception rules through HttpSecurity, which include the following:
(1) The login interface is login.html under static
(2) Formulate the url path for form login

When accessing, you will see the following interface:

Insert image description here

2.2.3 403 problem resolution

Enter your account and password, click login, and report an error:

Insert image description here

Problem:
In order to prevent the occurrence of CSRF (Cross-site request forgery), Spring security restricts most methods except get.

Insert image description here

Solution :
Shield CSRF control, that is, spring security no longer restricts CSRF.
ConfigureWebSecurityConfig

@Override
protected void configure(HttpSecurity http) throws Exception {
    
    
  //屏蔽CSRF控制,即spring security不再限制CSRF      
  http.csrf().disable() 
...
}
2.2.4 Modify login parameter name

The default account and password parameter names are: username, password, which must correspond to the background before normal login can be performed. Of course, Spring Security also provides the ability to modify the parameter names.

Configuration:

  .formLogin().
   							//自定义登录页面
                loginPage("/loginPage").
               //当发现/login时认为是登录,必须和表单提交的地址一样。
                loginProcessingUrl("/login").
                //登录成功后调整页面
                successForwardUrl("/main").
                //登录失败后跳转页面
                .failureForwardUrl("/toError");
                //自定义账号密码参数名
                usernameParameter("uname").
                passwordParameter("passwd");

Test method: Modify the parameter name in the interface and see if you can log in later. If you cannot log in, add the configuration and restart to log in. If the login is successful, verify that the configuration takes effect.

2.2.5 Logout configuration

Spring security implements logout exit and access/logout by default. As expected, Spring also does the exit function for us.

You can also customize the login operation in Spring Security.
The configuration is as follows:

.and() 
.logout() 
.logoutUrl("/logout")
.logoutSuccessUrl("/logoutSuccess");

controller code

@RequestMapping("/logoutSuccess")
public String logout1(){
    return "logout";
}

interface:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
登出界面
</body>
</html>
2.2.6 Custom login success handler

The bottom layer of the successForwardUrl that successfully logs in is the action of request forwarding, which cannot be used in projects where the front and back ends are separated.

Code:

public class MyAuthenticationSuccessHandler
        implements   {
    
    
    private String url;
    public MyAuthenticationSuccessHandler(String url) {
    
    
        this.url = url;
    }
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
                                        HttpServletResponse response,
                                        Authentication authentication)
            throws IOException, ServletException {
    
    
        User user = (User)authentication.getPrincipal();
        System.out.println(user.getUsername());
        System.out.println(user.getPassword());
        System.out.println(user.getAuthorities());
        response.sendRedirect(this.url);
    }
}

Configuration:

   http .formLogin().
                    loginPage("/login.html").
                    loginProcessingUrl("/login").
                    successHandler(new SuccessAuthenticationSuccessHandler("http://www.baidu.com")).

successHandler: When the login is successful, it will be handed over to our own defined processor for processing.

2.2.7 Custom login failure handler

Code:

public class FailAuthenticationFailureHandler implements AuthenticationFailureHandler {
    
    
    private String url;

    public FailAuthenticationFailureHandler(String url) {
    
    
        this.url = url;
    }

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
    
    
        response.sendRedirect(url);

    }
}

Configuration:

http.formLogin().
                    loginPage("/login.html").
                    loginProcessingUrl("/login").
                    successHandler(new SuccessAuthenticationSuccessHandler("http://www.baidu.com")).
                    failureHandler(new FailAuthenticationFailureHandler("http://www.baidu.com")).

failureHandler: When the login fails, it is handled by our own defined processor.

2.3 Authorization

2.3.1 Configuration mode authorization

Implementing authorization requires intercepting and verifying user access to verify whether the user's permissions can operate the specified resources. Spring Security provides authorization implementation methods by default.

Add /r/r1 or /r/r2 to LoginController

   @GetMapping("/r/r1")
    public String r1() {
    
    
        return " 访问资源1";
    }

    @GetMapping("/r/r2")
    public String r2() {
    
    
        return " 访问资源2";
    }

Configure authorization rules in the security configuration class WebSecurityConfifig.java:

.antMatchers("/r/r1").hasAuthority("p1") .antMatchers("/r/r2").hasAuthority("p2")

Configuration explanation:

  • .antMatchers("/r/r1").hasAuthority("p1") means: accessing the URL of the /r/r1 resource requires p1 permission.
  • .antMatchers("/r/r2").hasAuthority("p2") means: the url that accesses the /r/r2 resource needs to have p2

test:

1. Log in successfully

2. Access /r/r1 and /r/r2. If you have permission, access normally, otherwise return 403 (Access Denied)

Note: This method needs to be configured in SpringSecurityConfig, which has certain flaws. If there are hundreds of interfaces in the background, each of which needs to be configured in this method, it will be particularly confusing. SpringSecurity also provides another method. The annotation method is used more often. Of course, the use of more annotations does not mean that the annotation method will definitely be used in the projects we go out to do.

NOTE: The order of rules is important as more specific rules should be written first.

for example:

.antMatchers("/admin/**").hasRole("ADMIN") .antMatchers("/admin/login").permitAll()

Writing /admin/login in this way will also be intercepted.

The order should be reversed

.antMatchers("/admin/login").permitAll() .antMatchers("/admin/**").hasRole("ADMIN")
2.3.2 Common configurations

Commonly used methods to protect URLs include:

authenticated() protects the URL and requires user login

permitAll() specifies that the URL does not need to be protected, general applications and static resource files

hasRole(String role) restricts access to a single role, the role will be incremented by "ROLE_". So "ADMIN" will be compared with "ROLE_ADMIN".

hasAuthority(String authority) restricts access to a single authority

**hasAnyRole(String… roles)** allows access by multiple roles.

hasAnyAuthority(String… authorities) allows multiple authority access.

access(String attribute) This method uses SpEL expressions, so complex restrictions can be created.

hasIpAddress(String ipaddressExpression) restricts IP addresses or subnets

2.3.3 Annotation authorization

Now we have mastered how to use http.authorizeRequests() to authorize web resources. Starting from Spring Security version 2.0, it supports the security of service layer methods. In this section, we learn three types of annotations: @PreAuthorize, @PostAuthorize, and @Secured.

We can enable annotation-based security using the @EnableGlobalMethodSecurity annotation on any @Configuration instance.

The following will enable Spring Security’s @Secured annotation.

Configuration:

@EnableGlobalMethodSecurity(securedEnabled = true)

Response code:

@GetMapping("/r/r1")
@Secured("ROLE_HR")
@ResponseBody
public String r1() {
    
    
    return " 访问资源1";
}

@GetMapping("/r/r2")
@ResponseBody
@Secured("ROLE_ADMIN")
public String r2() {
    
    
    return " 访问资源2";
}

Note: @Secured is generally used for role-based access control.

The following will enable Spring Security’s @PreAuthorize annotation.

Configuration:

@EnableGlobalMethodSecurity(prePostEnabled = true)

Corresponding java code:

    @PreAuthorize("hasAnyAuthority('p1')")
    @GetMapping(value = "/r/r1")
    public String r1() {
    
    
        return " 访问资源1";
    }

    @GetMapping(value = "/r/r2")
    @PreAuthorize("hasAnyAuthority('p2')")
    public String r2() {
    
    
        return " 访问资源2";
    }

Note: @PreAuthorize is generally based on permission access control and is used more often.

Guess you like

Origin blog.csdn.net/m0_52896752/article/details/132904967