SpringSecurity+OAuth2权限管理实战

Spring Security快速入门

官方文档:

Spring Security :: Spring Security

功能:

  • 身份认证(authentication)

  • 授权(authorization)

  • 防御常见攻击(protection against common attacks)

身份认证:

  • 身份认证是验证谁正在访问系统资源,判断用户是否为合法用户。认证用户的常见方式是要求用户输入用户名和密码。

授权:

  • 用户进行身份认证后,系统会控制谁能访问哪些资源,这个过程叫做授权。用户无法访问没有权限的资源。

防御常见攻击:

  • CSRF

  • HTTP Headers

  • HTTP Requests

1、身份认证(authentication)

官方代码示例:GitHub - spring-projects/spring-security-samples

1.1、创建Spring Boot项目

项目名:security-demo

JDK:17

SpringBoot:3.2.0(依赖了Spring Security 6.2.0)

Dependencies:Spring Web、Spring Security、Thymeleaf

1.2、创建IndexController

package com.atguigu.securitydemo.controller;
​
@Controller
public class IndexController {
​@GetMapping("/")public String index() {return "index";}
}

1.3、创建index.html

在路径resources/templates中创建index.html

<html xmlns:th="https://www.thymeleaf.org">
<head><title>Hello Security!</title>
</head>
<body>
<h1>Hello Security</h1>
<!--通过使用@{/logout},Thymeleaf将自动处理生成正确的URL,以适应当前的上下文路径。
这样,无论应用程序部署在哪个上下文路径下,生成的URL都能正确地指向注销功能。-->
<a th:href="@{/logout}">Log Out</a>
</body>
</html>

1.4、启动项目测试Controller

浏览器中访问:http://localhost:8080/

浏览器自动跳转到登录页面:http://localhost:8080/login

输入用户名:user

输入密码:在控制台的启动日志中查找初始的默认密码

点击"Sign in"进行登录,浏览器就跳转到了index页面

1.5、注意事项

1.5.1、@{/logout}的作用

通过使用@{/logout},Thymeleaf将自动处理生成正确的URL,以适应当前的上下文路径。这样,无论应用程序部署在哪个上下文路径下,生成的URL都能正确地指向注销功能。

例如:如果我们在配置文件中添加如下内容

server.servlet.context-path=/demo

那么@{/logout}可以自动处理url为正确的相对路径

但是如果是普通的/logout,路径就会不正确

1.5.2、页面样式无法加载的问题

页面样式bootstrap.min.css是一个CDN地址,需要通过科学上网的方式访问

否则你的登录页会加载很久,并且看到的页面是这样的(登录按钮没有样式文件渲染,但是不影响登录功能的执行)

1.6、Spring Security默认做了什么

  • 保护应用程序URL,要求对应用程序的任何交互进行身份验证。

  • 程序启动时生成一个默认用户“user”。

  • 生成一个默认的随机密码,并将此密码记录在控制台上。

  • 生成默认的登录表单和注销页面。

  • 提供基于表单的登录和注销流程。

  • 对于Web请求,重定向到登录页面;对于服务请求,返回401未经授权。

  • 处理跨站请求伪造(CSRF)攻击。

  • 处理会话劫持攻击。

  • 写入Strict-Transport-Security以确保HTTPS。

  • 写入X-Content-Type-Options以处理嗅探攻击。

  • 写入Cache Control头来保护经过身份验证的资源。

  • 写入X-Frame-Options以处理点击劫持攻击。

1.7创建项目

ide社区版本或者专业版2022-2023

服务器地址URL 阿里云脚手架 https://start.aliyun.com/

或者原来的即可

http://start.springboot.io/

Spring Web Spring Security Thymeleaf 三个选中

然后创建

IndexController
  // http://127.0.0.1:8080/@GetMapping("/")public String html(){return "index.html";}

templates/ index.html

<html xmlns:th="https://www.thymeleaf.org">
<head><title>Hello Security!</title>
</head>
<body>
<h1>Hello Security</h1>
<a th:href="@{/logout}">Log Out</a>
<a href="@{/logout}">Log Out2</a>
</body>
</html>

SecurityProperties

默认情况下Spring Security将初始的用户名和密码存在了SecurityProperties类中。这个类中有一个静态内部类User,配置了默认的用户名(name = "user")和密码(password = uuid)

spring.security.user.name=user
spring.security.user.password=123

WebSecurityConfig

package com.smg.securitydemo.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;@Configuration
@EnableWebSecurity//Spring项目总需要添加此注解,SpringBoot项目中不需要
public class WebSecurityConfig {@Beanpublic UserDetailsService userDetailsService() {InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();manager.createUser( //此行设置断点可以查看创建的user对象User.withDefaultPasswordEncoder().username("huan") //自定义用户名.password("password") //自定义密码.roles("USER") //自定义角色.build());return manager;}
}

 http://127.0.0.1:8080/

之前密码不可用

2、基于数据库的数据源

2.1、SQL

创建三个

- 创建数据库
CREATE DATABASE `security-demo`;
USE `security-demo`;-- 创建用户表
CREATE TABLE `user`(`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,`username` VARCHAR(50) DEFAULT NULL ,`password` VARCHAR(500) DEFAULT NULL,`enabled` BOOLEAN NOT NULL
);
-- 唯一索引
CREATE UNIQUE INDEX `user_username_uindex` ON `user`(`username`); -- 插入用户数据(密码是 "abc" )
INSERT INTO `user` (`username`, `password`, `enabled`) VALUES
('admin', '{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW', TRUE),
('Helen', '{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW', TRUE),
('Tom', '{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW', TRUE);

数据库表并插入测试数据

2.2、引入依赖

 <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.4.1</version><exclusions><exclusion><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>3.0.3</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.10</version></dependency>

2.3、配置数据源

#MySQL数据源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/security-demo
spring.datasource.username=root
spring.datasource.password=123456
#SQL日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

2.4、实体类

package com.smg.securitydemo.entity;@Data
public class User {@TableId(value = "id", type = IdType.AUTO)private Integer id;private String username;private String password;private Boolean enabled;}

2.5、Mapper

package com.smg.securitydemo.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.smg.securitydemo.entity.User;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface UserMapper extends BaseMapper<User> {
}

xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.smg.securitydemo.mapper.UserMapper"></mapper>

2.6、Service

package com.smg.securitydemo.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.smg.securitydemo.entity.User;public interface UserService extends IService<User> {
}

实现

package com.smg.securitydemo.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smg.securitydemo.entity.User;
import com.smg.securitydemo.mapper.UserMapper;
import com.smg.securitydemo.service.UserService;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

2.7、Controller

package com.smg.securitydemo.controller;import com.smg.securitydemo.entity.User;
import com.smg.securitydemo.service.UserService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
@RequestMapping("/user")
public class UserController {//localhost:8080/demo/user/list@Resourcepublic UserService userService;@GetMapping("/list")public List<User> getList(){return userService.list();}
}

登录失败

原因springboot版本太新导致不兼容

修改过后即可访问

   <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.4.1</version><exclusions><exclusion><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>3.0.3</version></dependency>

修改过后登录即可

3、基于数据库的用户认证

3.1、基于数据库的用户认证流程

3.2、定义DBUserDetailsManager

package com.smg.securitydemo.config;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.smg.securitydemo.entity.User;
import com.smg.securitydemo.mapper.UserMapper;
import jakarta.annotation.Resource;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsPasswordService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.provisioning.UserDetailsManager;import java.util.ArrayList;
import java.util.Collection;public class DBUserDetailsManager implements UserDetailsManager, UserDetailsPasswordService {@Resourceprivate UserMapper userMapper;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.eq("username", username);User user = userMapper.selectOne(queryWrapper);if (user == null) {throw new UsernameNotFoundException(username);} else {Collection<GrantedAuthority> authorities = new ArrayList<>();return new org.springframework.security.core.userdetails.User(user.getUsername(),user.getPassword(),user.getEnabled(),true, //用户账号是否过期true, //用户凭证是否过期true, //用户是否未被锁定authorities); //权限列表}}@Overridepublic UserDetails updatePassword(UserDetails user, String newPassword) {return null;}@Overridepublic void createUser(UserDetails user) {}@Overridepublic void updateUser(UserDetails user) {}@Overridepublic void deleteUser(String username) {}@Overridepublic void changePassword(String oldPassword, String newPassword) {}@Overridepublic boolean userExists(String username) {return false;}}

3.3、初始化UserDetailsService

修改WebSecurityConfig中的userDetailsService方法如下

  @Beanpublic UserDetailsService userDetailsService() {DBUserDetailsManager manager = new DBUserDetailsManager();return manager;}

注意需要注释掉原来的代码

遇到这种问题

在 

WebSecurityConfig中创建对应缺少的类
@Bean
public DBUserDetailsManager2 dbUserDetailsManager2() {// 创建DBUserDetailsManager2的实例,这里可能需要注入其他依赖,如JdbcTemplate等return new DBUserDetailsManager2();
}

登录数据库里的账号如admin

Swagger测试地址:http://localhost:8080/demo/doc.html

6、密码加密算法

参考文章

https://docs.spring.io/spring-security/reference/features/authentication/password-storage.html

6.1、密码加密方式

明文密码:

项目地址

security-demo: security-demo

oauth2-login-demo: oauth2-login-demo

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/461040.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Java][算法 双指针]Day 02---LeetCode 热题 100---04~07

LeetCode 热题 100---04~07 第一题&#xff1a;移动零 思路 找到每一个为0的元素 然后移到数组的最后 但是需要注意的是 要在给定的数组原地进行修改 并且其他非零元素的相对顺序不能改变 我们采用双指针法 定义两个指针i和j i和j一开始分别都在0索引位置 然后判断j所…

MQTT 服务器(emqx)搭建及使用

推荐阅读&#xff1a; MQTT 服务器(emqx)搭建及使用 - 哔哩哔哩 (bilibili.com) 一、EMQX 服务器搭建 1、下载EMQX https://www.emqx.com/zh/try?productbroker 官方中文手册&#xff1a; EMQX Docs 2、安装使用 1、该软件为绿色免安装版本&#xff0c;解压缩后即安装完…

第三百一十五回

文章目录 1. 概念介绍2. 基本用法3. 补充用法4. 内容总结 我们在上一章回中介绍了"再谈ListView中的分隔线"&#xff0c;本章回中将介绍showMenu的用法.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在第一百六十三回中介绍了showMenu相关的内容…

商业智能(BI)数据分析、挖掘概念

商业智能&#xff08;BI&#xff09;数据分析挖掘概念 一、商业智能&#xff08;BI&#xff09;数据分析挖掘概念 数据挖掘目前在各类企业和机构中蓬勃发展。因此我们制作了一份此领域常见术语总结。 1.分析型客户关系管理&#xff08;Analytical CRM/aCRM 用于支持决策&…

基于华为云欧拉操作系统(HCE OS)单节点容器化部署(Prometheus、node-exporter、Grafana)应用性能监控平台

写在前面 博文内容为 华为云欧拉操作系统入门级开发者认证(HCCDA – Huawei Cloud EulerOS)实验笔记整理认证地址&#xff1a;https://edu.huaweicloud.com/certificationindex/developer/9bf91efb086a448ab4331a2f53a4d3a1内容涉及&#xff0c;HCE OS 容器化部署(Prometheus、…

Jumserver 安装

一、Jumserver 官网地址 Jumserver官网地址 二、Jumserver的基本概率 1、4a概率 首先&#xff0c;堡参机提供了运维安全审计的4A规范 Authentication: 身份鉴别&#xff0c;防止身份冒用和复用(开发10人&#xff0c;测试5人&#xff0c;运维2人&#xff09; Authorizatton:授…

【Linux】进程学习(一):基本认识

目录 1.基本概念2.初步理解3.描述进程-PCB3.1task_struct-PCB的一种3.2task_ struct内容分类 4.组织进程5.查看进程5.1通过ps指令查看5.2通过系统目录查看 6.通过系统调用获取进程的PID和PPID7.通过系统调用创建进程-fork初识 1.基本概念 课本概念&#xff1a;程序的一个执行实…

计算机网络——05Internet结构和ISP

Internet结构和ISP 互连网络结构&#xff1a;网络的网络 端系统通过接入ISPs连接到互连网 住宅、公司和大学的ISPs 接入ISPs相应的必须是互联的 因此任何2个端系统可相互发送分组到对方 导致的“网络的网络”非常复杂 发展和演化是通过经济的和国家的政策来驱动的 问题&…

Elasticsearch:通过 ingest pipeline 对大型文档进行分块

在我之前的文章 “Elasticsearch&#xff1a;使用 LangChain 文档拆分器进行文档分块” 中&#xff0c;我详述了如何通过 LangChain 对大的文档进行分块。那个分块的动作是通过 LangChain 在 Python 中进行实现的。对于使用版权的开发者来说&#xff0c;我们实际上是可以通过 i…

在虚拟机上搭建CentOS环境并配置静态IP

在虚拟机上搭建CentOS环境并配置静态IP 在进行Linux系统的学习和实践时&#xff0c;搭建一个本地的CentOS环境是一个非常好的方式。本文将介绍如何使用虚拟机&#xff08;VM&#xff09;搭建CentOS环境&#xff0c;并配置静态IP&#xff0c;以便更好地进行网络管理和测试。 步…

结构体的大小以及内存对齐问题

结构体的大小怎么计算&#xff1f;什么是结构体的对齐&#xff1f; 首先想要直到结构体的大小需要先了解结构体的内存对齐。那么&#xff0c;什么是结构体的内存对齐&#xff1a; 什么是结构体内存对齐 结构体的对齐 就是 结构体类型数据在内存中按照一定的对齐规律储存。结…

jvm问题自查思路

本文聊一下最近处理了一些jvm的问题上&#xff0c;将这个排查和学习过程分享一下&#xff0c;看了很多资料&#xff0c;最终都会落地到几个工具的使用&#xff0c;本文主要是从文档学习、工具学习和第三方技术验证来打开认知和实践&#xff0c;希望有用。 一、文档 不仅知道了…