自学内容网 自学内容网

SpringSecurity基于默认数据库模型的认证与授权

在 Spring Security 中,默认的认证和授权机制依赖于一套内置的数据库模型,通常涉及用户(User)、角色(Role)和权限(Authority)等实体。

除了 InMemoryUserDetailsManager,Spring Security 还提供另一个 UserDetailsService 实现类: JdbcUserDetailsManager。 JdbcUserDetailsManager 帮助我们以 JDBC 的方式对接数据库和 Spring Security,它设定了一个默认的数据库模型,只要遵从这个模型,在简便性上,JdbcUserDetailsManager 甚至可以媲美 InMemoryUserDetailsManager。

1、数据库准备

(1)创建默认数据库模型

使用 MySQL 数据库,创建 Spring Security 提供的默认表。JdbcUserDetailsManager 需要两个表,其中 users 表用来存放用户名、密码和是否可用三个信息,authorities 表用来存放用户名及其权限的对应关系。

-- 创建数据库
CREATE DATABASE IF NOT EXISTS db_admin; 

USE db_admin;

-- 创建 Spring Security 提供的表
CREATE TABLE users (
  username VARCHAR (50) NOT NULL PRIMARY KEY,
  PASSWORD VARCHAR (500) NOT NULL,
  enabled BOOLEAN NOT NULL
) ;

CREATE TABLE authorities (
  username VARCHAR (50) NOT NULL,
  authority VARCHAR (50) NOT NULL,
  CONSTRAINT fk_authorities_users FOREIGN KEY (username) REFERENCES users (username)
) ;

CREATE UNIQUE INDEX ix_auth_username ON authorities (username,authority);

-- 查询
SELECT * FROM users;
SELECT * FROM authorities;

(2)添加 Maven 依赖

在 pom.xml 配置文件中添加 Spring Security 依赖、JDBC 相关依赖、Thymeleaf 模板引擎。

<!-- Spring Security 依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>2.7.18</version>
</dependency>

<!--Spring Boot 的 JDBC 支持 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>

<!-- MySQL 的 JDBC 数据库驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

<!-- 引入Thymeleaf模板引擎 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

(3)配置数据库连接参数

在项目的 application.yml 文件中,添加数据库连接的配置。

spring:
  # 使用Thymeleaf模板引擎
  thymeleaf:
    mode: HTML5
    encoding: UTF-8
    cache: false
    servlet:
      content-type: text/html
  # 数据库连接
  datasource:
    url: jdbc:mysql://localhost:3306/db_admin?useSSL=false&amp&serverTimezone=UTC
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver

2、实现认证与授权

(1)创建配置类(核心代码)

创建 WebSecurityConfig 类(Spring Security 配置类),并添加 @EnableWebSecurity 注解和继承 WebSecurityConfigurerAdapter 类。

JdbcUserDetailsManager 与 InMemoryUserDetailsManager 在用法上没有太大区别,只是多了设置 DataSource 的环节。 Spring Security 通过 DataSource 执行设定好的命令。例如,此时的 createUser 函数实际上执行了SQL 语句,将设置的用户与权限信息添加到数据表中。

package com.pjb.securitydemo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.JdbcUserDetailsManager;

import javax.sql.DataSource;

/**
 * Spring Security 配置类
 * @author pan_junbiao
 **/
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
    @Autowired
    private DataSource dataSource;

    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
        http.authorizeRequests() //返回一个URL拦截注册器
                .antMatchers("/admin/api/**").hasRole("ADMIN") //设置授权角色
                .antMatchers("/user/api/**").hasRole("USER") //设置授权角色
                .antMatchers("/app/api/**", "/captcha.jpg").permitAll() //公开其权限
                .anyRequest() //匹配所有的请求
                .authenticated() //所有匹配的URL都需要被认证才能访问
                .and() //结束当前标签,让上下文回到 HttpSecurity
                .formLogin() //启动表单认证
                .and().csrf().disable(); //关闭CSRF的防御功能
    }

    /**
     * JDBC添加登录账号
     */
    @Bean
    public UserDetailsService userDetailsService()
    {
        JdbcUserDetailsManager manager = new JdbcUserDetailsManager();
        manager.setDataSource(dataSource); //设置数据源

        if (!manager.userExists("admin"))
        {
            manager.createUser(User.withUsername("admin").password("123456").roles("ADMIN").build());
        }

        if (!manager.userExists("user"))
        {
            manager.createUser(User.withUsername("user").password("123456").roles("USER").build());
        }

        if (!manager.userExists("panjunbiao"))
        {
            manager.createUser(User.withUsername("panjunbiao").password("123456").roles("USER").build());
        }

        return manager;
    }

    /**
     * 由于5.x版本之后默认启用了委派密码编译器,
     * 因而按照以往的方式设置内存密码将会读取异常,
     * 所以需要暂时将密码编码器设置为 NoOpPasswordEncoder
     */
    @Bean
    public PasswordEncoder passwordEncoder()
    {
        return NoOpPasswordEncoder.getInstance();
    }
}

(2)编写控制器类

创建 IndexController 控制器类,实现跳转到首页,同时获取当前登录人的名称。

package com.pjb.securitydemo.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
 
import javax.servlet.http.HttpServletRequest;
import java.security.Principal;
 
/**
 * 首页控制器
 * @author pan_junbiao
 **/
@Controller
public class IndexController
{
    /**
     * 首页
     */
    @RequestMapping("/")
    public String index(HttpServletRequest request)
    {
        //获取当前登录人
        String userName = "未登录";
        Principal principal = request.getUserPrincipal();
        if(principal!=null)
        {
            userName = principal.getName();
        }
 
        //返回页面
        request.setAttribute("userName",userName);
        return "/index.html";
    }
 
}

(3)编写首页

在 resources\templates 资源目录下,创建 index.html 页面。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
    <meta name="author" content="pan_junbiao的博客">
</head>
<body>
    <h1 style="color: red">Hello,Spring Security</h1>
    <p>博客信息:您好,欢迎访问 pan_junbiao的博客</p>
    <p>博客地址:https://blog.csdn.net/pan_junbiao</p>
    <p th:text="'当前登录人:' + ${userName}"></p>
    <a href="/logout" onclick="return confirm('确认注销吗?');">登出</a>
</body>
</html>

(4)运行项目

当项目启动成功后,查看数据库表,会发现用户信息与权限信息已成功添加到数据表中。

(5)登录页面

(6)成功登录后,跳转至首页


原文地址:https://blog.csdn.net/pan_junbiao/article/details/143991943

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!