• Spring Security 入门—内存用户验证


    简介

    作为 Spring 全家桶组件之一,Spring Security 是一个提供安全机制的组件,它主要解决两个问题:

    • 认证:验证用户名和密码;
    • 授权:对于不同的 URL 权限不一样,只有当认证的用户拥有某个 URL 的需要的权限时才能访问。

    Spring Security 底层使用的是过滤器,针对 URL 进行的拦截,对应到 Java 中也就是类; 因此被称为粗粒度授权验证,就是验证 URL ,当前用户是否有这个 URL 的权限。

    入门

    创建项目

    使用 Idea 创建 Spring Boot 项目,勾选需要的组件:

    • Spring Web
    • Spring Security

    或者创建项目后添加依赖:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    

    这里使用的是 JSP 作为模板,有关如何在 Spring Boot 中使用 JSP 作为模板请访问:https://www.cnblogs.com/cloudfloating/p/11787222.html

    WebSecurityConfig

    package top.cloudli.demo.security;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    
    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled=true)
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            PasswordEncoder encoder = new BCryptPasswordEncoder();
            
            auth.inMemoryAuthentication()
                    .passwordEncoder(encoder)
                    .withUser("root")
                    .password(encoder.encode("root@123456"))
                    .roles("ROOT", "USER")
                    .and()
                    .withUser("user")
                    .password(encoder.encode("user@123456"))
                    .roles("USER");
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .antMatchers("/css/**")
                    .permitAll()        // css 不用验证
                    .anyRequest()
                    .authenticated()    // 其它页面全部需要验证
                    .and()
                    .formLogin()        // 使用默认登录页面
                    .and()
                    .exceptionHandling()
                    .accessDeniedPage("/401")   // 无权限时跳转的页面
                    .and()
                    .logout();
        }
    }
    
    • @EnableWebSecurity 注解启用验证;
    • @EnableGlobalMethodSecurity(prePostEnabled=true) 注解允许我们在控制器的方法中使用 @PreAuthorize 实现权限分割。

    此处创建了两个用户并保存在内存中,分别是拥有 ROOT 和 USER 权限的 root 用户和仅拥有 USER 权限的 user 用户。

    fromLogin() 方法可以接着调用 loginPage() 指定一个自定义登录页面,这里使用的是默认登录页面。

    编写页面

    1.index.jsp,所有通过验证的用户都可以访问:

    <%--
      任何通过验证的用户都能访问的页面
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Spring Security Demo Application</title>
        <link rel="stylesheet" type="text/css" href="css/style.css">
    </head>
    <body>
    <div class="content">
        <h1>Spring Security In Memory Authentication</h1>
        <h2>这是被保护的页面(ROLE_USER)。</h2>
    </div>
    </body>
    </html>
    

    2.root.jsp,只有拥有 ROOT 权限的用户能访问:

    <%--
      需要 ROLE_ROOT 才能访问的页面
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Root Page</title>
        <link rel="stylesheet" type="text/css" href="css/style.css">
    </head>
    <body>
    <div class="content">
        <h1>Root Page</h1>
        <h2>你正在访问受保护的页面(ROLE_ROOT)。</h2>
    </div>
    </body>
    </html>
    

    3.401.jsp,没有权限时跳转的页面:

    <%--
      权限不够时跳转的页面
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>401 Unauthorized</title>
        <link rel="stylesheet" type="text/css" href="css/style.css">
    </head>
    <body class="error">
    <div class="content">
        <h1>401 Unauthorized!</h1>
        <h2>你没有权限访问此页面。</h2>
    </div>
    </body>
    </html>
    

    控制器

    package top.cloudli.demo.controller;
    
    import org.springframework.security.access.prepost.PreAuthorize;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    
    @Controller
    public class DemoController {
    
        @PreAuthorize("hasAnyAuthority('ROLE_USER')")
        @GetMapping("/")
        public String index() {
            return "index";
        }
    
        @PreAuthorize("hasAnyAuthority('ROLE_ROOT')")
        @GetMapping("/root")
        public String root() {
            return "root";
        }
    
        @GetMapping("/401")
        public String accessDenied() {
            return "401";
        }
    }
    

    @PreAuthorize 注解指定了访问页面所需要的权限,这里的权限要加上 ROLE_ 前缀。

    Run

    访问 http://localhost:8080/ 将进入登录页面(这里使用的是 Spring Security 的默认登录页面):

    image

    使用刚才创建的内存用户 user 登录后将返回 index 页面:

    image

    访问 http://localhost:8080/root,由于 user 用户没有 ROLE_ROOT 权限,跳转到 401 页面:

    image

    访问 http://localhost:8080/logout 将进入默认登出页面:

    image

    这里的登录和登出页面均可以使用自定义页面,只需要在自定义的页面中把数据通过 PSOT 请求提交到 /login/logout 即可完成登录和登出。

  • 相关阅读:
    docker-compose运行nginx
    docker后台持续运行
    docker-compose运行tomcat
    集群session解决方案
    docker运行mysql
    docker运行svn
    mongodb数据的导出和导入
    mongodb副本集的docker化安装
    grafana使用json数据源监控数据
    docker化安装grafana
  • 原文地址:https://www.cnblogs.com/cloudfloating/p/11826083.html
Copyright © 2020-2023  润新知