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&&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)!