Spring Security
Spring Security
2023-06-13 09:13:09 时间
# 简介
身份验证和访问控制的框架
- 扩展度高
- 对比shiro
spring security | shiro |
---|---|
配置复杂 | |
社区支持好 | |
boot项目用 | |
spring mvc用 | |
跨平台,可以独立运行 | |
仅支持spring |
# 项目搭建
springBoot 2.5.5 + Mybatis + Spring Security 5.x
Spring Security 5.0+ 变化版本较多,且不兼容之前的版本,确保你的springBoot版本为2.0。
- 添加依赖,注意mysql包
<dependencies>
<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>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.27</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
# 模板语法
jsp
thymeleaf
默认开启表单认证,用户名user,密码在控制台输出
# httpBasic认证(不用)
注意添加configuration注解
package com.zr.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
super.configure(auth);
}
@Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//开启httpBasic认证
http.httpBasic()
//每个模块配置使用and结尾
.and()
//配置路径拦截,表明路径访问所对应的权限,角色,认证信息
.authorizeRequests()
.anyRequest()
//所有请求都需要登录认证才能访问
.authenticated();
}
}
# 自定义账户密码
修改yaml配置文件
spring:
security:
user:
name: px
password: 1234
# 表单认证
添加配置类,可以修改用户密码字段名,与前端对应上。
package com.zr.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
super.configure(auth);
}
@Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login.html","/login")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/login")
.usernameParameter("userId")
.passwordParameter("password")
.defaultSuccessUrl("/home");
//关闭跨域攻击防护
http.csrf().disable();
}
}
# 权限认证
配置权限 PasswordEncoder接口,常用BCryptPasswordEncoder实现类
http.authorizeRequests()
.antMatchers("/login.html","/login")
.permitAll()
.antMatchers("/user","/role")
.hasAnyAuthority("ROLE_user","ROLE_admin")
.antMatchers("/auth","/others")
.hasAnyAuthority("ROLE_admin")
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/login")
.usernameParameter("username")
.passwordParameter("password")
.defaultSuccessUrl("/home");
//关闭跨域攻击防护
http.csrf().disable();
密码加密,有盐值,需要用matches方法判断密码是否匹配
package com.zr;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.security.crypto.password.PasswordEncoder;
@SpringBootTest
public class SecurityTest {
@Autowired
private PasswordEncoder passwordEncoder;
@Test
public void testPassword(){
String pwd1 = passwordEncoder.encode("1234");
String pwd2 = passwordEncoder.encode("1234");
System.out.println("加密字符串[1234]"+pwd1);
System.out.println("加密字符串[1234]"+pwd2);
System.out.println("判断pwd1是否为[1234]"+passwordEncoder.matches("1234",pwd1));
System.out.println("判断pwd1是否为[1234]"+passwordEncoder.matches("1234",pwd2));
System.out.println("盐值"+BCrypt.gensalt());
System.out.println("盐值"+BCrypt.gensalt());
}
}
内存中创建用户角色
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//内存中配置用户和角色信息
auth.inMemoryAuthentication()
//设置用户
.withUser("px")
//设置密码
.password(passwordEncoder.encode("1234"))
//设置角色,注意:角色缺省ROLE_
.roles("user")
.and()
.withUser("admin")
.password(passwordEncoder.encode("1234"))
.roles("admin")
.and()
//设置密码加密算法
.passwordEncoder(passwordEncoder);
}
数据库
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`user_id` varchar(32) NOT NULL COMMENT '账号',
`user_name` varchar(32) NOT NULL COMMENT '用户名',
`user_type` varchar(2) DEFAULT NULL COMMENT '用户类型(00系统用户)',
`email` varchar(50) DEFAULT NULL COMMENT '用户邮箱',
`phonenumber` varchar(11) DEFAULT NULL COMMENT '手机号码',
`sex` char(1) DEFAULT NULL COMMENT '用户性别(0女 1男 2未知)',
`avatar` varchar(200) DEFAULT NULL COMMENT '头像地址',
`password` varchar(100) DEFAULT NULL COMMENT '用户密码',
`last_login_time` datetime DEFAULT NULL COMMENT '上一次登录时间',
`last_login_ip` varchar(128) DEFAULT NULL COMMENT '上一次登录地址',
`enabled` tinyint(1) DEFAULT '1' COMMENT '账号是否可用。默认为1(可用)',
`not_expired` tinyint(1) DEFAULT '1' COMMENT '是否过期。默认为1(没有过期)',
`account_not_locked` tinyint(1) DEFAULT '1' COMMENT '账号是否锁定。默认为1(没有锁定)',
`credentials_not_expired` tinyint(1) DEFAULT '1' COMMENT '证书(密码)是否过期。默认为1(没有过期)',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`create_user` varchar(32) DEFAULT NULL COMMENT '创建人',
`update_user` varchar(32) DEFAULT NULL COMMENT '修改人',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
`role_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`role_name` varchar(32) DEFAULT NULL COMMENT '角色名',
`role_sort` int(11) DEFAULT NULL COMMENT '显示顺序',
`role_remark` varchar(64) DEFAULT NULL COMMENT '角色说明',
PRIMARY KEY (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色表';
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
`user_id` varchar(32) DEFAULT NULL,
`role_id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `sys_auth`;
CREATE TABLE `sys_auth` (
`auth_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '权限ID',
`auth_name` varchar(50) NOT NULL COMMENT '权限(菜单)名称',
`parent_id` int(11) DEFAULT '0' COMMENT '父菜单ID',
`auth_sort` int(4) DEFAULT '0' COMMENT '显示顺序',
`path` varchar(200) DEFAULT '' COMMENT '路由地址',
`component` varchar(255) DEFAULT NULL COMMENT '组件路径',
`query` varchar(255) DEFAULT NULL COMMENT '路由参数',
`auth_type` char(1) DEFAULT '' COMMENT '权限(菜单)类型(M目录 C菜单 F按钮)',
`visible` char(1) DEFAULT '0' COMMENT '菜单状态(0隐藏 1显示)',
`perms` varchar(100) DEFAULT NULL COMMENT '权限标识',
`icon` varchar(100) DEFAULT '#' COMMENT '菜单图标',
`status` char(1) DEFAULT '0' COMMENT '菜单状态(0正常 1停用)',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`create_user` varchar(32) DEFAULT '' COMMENT '创建人',
`update_user` varchar(32) DEFAULT '' COMMENT '修改人',
`remark` varchar(500) DEFAULT '' COMMENT '备注',
PRIMARY KEY (`auth_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1067 DEFAULT CHARSET=utf8 COMMENT='菜单权限表';
DROP TABLE IF EXISTS `sys_role_auth`;
CREATE TABLE `sys_role_auth` (
`role_id` int(11) DEFAULT NULL COMMENT '角色ID',
`auth_id` int(11) DEFAULT NULL COMMENT '权限ID'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
添加数据
INSERT INTO `sys_user` (`user_id`, `user_name`, `user_type`, `email`, `phonenumber`, `sex`, `avatar`, `password`, `last_login_time`, `last_login_ip`, `enabled`, `not_expired`, `account_not_locked`, `credentials_not_expired`, `create_time`, `update_time`, `create_user`, `update_user`) VALUES ('admin', '管理员', '1', NULL, NULL, '男', NULL, '$2a$10$K.QFed/vCaI0pBIoCQ/iP.IPI9tNF4XdnZ53a0n6OJ3bZTcs5iFpO', NULL, NULL, '1', '1', '1', '1', NULL, NULL, NULL, NULL);
INSERT INTO `sys_user` (`user_id`, `user_name`, `user_type`, `email`, `phonenumber`, `sex`, `avatar`, `password`, `last_login_time`, `last_login_ip`, `enabled`, `not_expired`, `account_not_locked`, `credentials_not_expired`, `create_time`, `update_time`, `create_user`, `update_user`) VALUES ('zr', '中软', '1', NULL, NULL, '男', NULL, '$2a$10$Y6M/tp8V2vIe5b7C851ISe568ph8YwK/4cYltURIPRERDINC0IgRK', NULL, NULL, '1', '1', '1', '1', NULL, NULL, NULL, NULL);
INSERT INTO `sys_role` (`role_id`, `role_name`, `role_sort`, `role_remark`) VALUES ('1', '普通用户', '1', 'ROLE_user');
INSERT INTO `sys_role` (`role_id`, `role_name`, `role_sort`, `role_remark`) VALUES ('2', '管理员', '2', 'ROLE_admin');
INSERT INTO `sys_user_role` (`user_id`, `role_id`) VALUES ('zr', '1');
INSERT INTO `sys_user_role` (`user_id`, `role_id`) VALUES ('admin', '2');
INSERT INTO `sys_auth` (`auth_id`, `auth_name`, `parent_id`, `auth_sort`, `path`, `component`, `query`, `auth_type`, `visible`, `perms`, `icon`, `status`, `create_time`, `update_time`, `create_user`, `update_user`, `remark`) VALUES ('1', '用户管理', NULL, '1', '', NULL, NULL, 'C', '0', NULL, '#', '0', NULL, NULL, '', '', '');
INSERT INTO `sys_auth` (`auth_id`, `auth_name`, `parent_id`, `auth_sort`, `path`, `component`, `query`, `auth_type`, `visible`, `perms`, `icon`, `status`, `create_time`, `update_time`, `create_user`, `update_user`, `remark`) VALUES ('2', '角色管理', NULL, '2', '', NULL, NULL, 'C', '0', NULL, '#', '0', NULL, NULL, '', '', '');
INSERT INTO `sys_auth` (`auth_id`, `auth_name`, `parent_id`, `auth_sort`, `path`, `component`, `query`, `auth_type`, `visible`, `perms`, `icon`, `status`, `create_time`, `update_time`, `create_user`, `update_user`, `remark`) VALUES ('3', '权限管理', NULL, '3', '', NULL, NULL, 'C', '0', NULL, '#', '0', NULL, NULL, '', '', '');
INSERT INTO `sys_auth` (`auth_id`, `auth_name`, `parent_id`, `auth_sort`, `path`, `component`, `query`, `auth_type`, `visible`, `perms`, `icon`, `status`, `create_time`, `update_time`, `create_user`, `update_user`, `remark`) VALUES ('4', '其它管理', NULL, '4', '', NULL, NULL, 'C', '0', NULL, '#', '0', NULL, NULL, '', '', '');
INSERT INTO `sys_auth` (`auth_id`, `auth_name`, `parent_id`, `auth_sort`, `path`, `component`, `query`, `auth_type`, `visible`, `perms`, `icon`, `status`, `create_time`, `update_time`, `create_user`, `update_user`, `remark`) VALUES ('5', '用户查询', '1', '1', '', NULL, NULL, 'F', '0', 'sys:user:list', '#', '0', NULL, NULL, '', '', '');
INSERT INTO `sys_auth` (`auth_id`, `auth_name`, `parent_id`, `auth_sort`, `path`, `component`, `query`, `auth_type`, `visible`, `perms`, `icon`, `status`, `create_time`, `update_time`, `create_user`, `update_user`, `remark`) VALUES ('6', '用户新增', '1', '2', '', NULL, NULL, 'F', '0', 'sys:user:add', '#', '0', NULL, NULL, '', '', '');
INSERT INTO `sys_role_auth` (`role_id`, `auth_id`) VALUES ('1', '1');
INSERT INTO `sys_role_auth` (`role_id`, `auth_id`) VALUES ('1', '2');
INSERT INTO `sys_role_auth` (`role_id`, `auth_id`) VALUES ('1', '5');
反向生成mapper
通过数据库设置角色
package com.zr.service.security.impl;
import com.zr.mapper.sys.SysRoleMapper;
import com.zr.mapper.sys.SysUserMapper;
import com.zr.vo.sys.SysRole;
import com.zr.vo.sys.SysUser;
import org.springframework.context.annotation.Primary;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Service
@Primary
public class UserDetailsServiceImpl implements UserDetailsService {
@Resource
private SysUserMapper sysUserMapper;
@Resource
private SysRoleMapper sysRoleMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//根据登录账户获取用户信息
SysUser sysUser= sysUserMapper.selectByPrimaryKey(username);
if(sysUser == null) throw new UsernameNotFoundException("用户账户不存在");
List<SysRole> sysRoleList = sysRoleMapper.selectByUserId(username);
//权限集合
Set<GrantedAuthority> authorities = new HashSet<>();
for(SysRole sysRole:sysRoleList){
authorities.add(new SimpleGrantedAuthority(sysRole.getRoleRemark()));
}
return new User(username, sysUser.getPassword(), authorities);
}
}
相关文章
- 玩转 Spring Boot 集成篇(@Scheduled、静态、动态定时任务)(七)
- 将 Bean 放入 Spring 容器中的五种方式 !
- Spring-Retry 和 Guava-Retry,各有千秋
- Spring Boot+Spring Security+JWT实现单点登录
- 真肝,整理了一周的Spring面试大全【含答案】,吊打Java面试官[通俗易懂]
- Spring Security 系列(3) —— Spring Security & Webflux
- 创建Spring Boot应用
- Spring Cloud实战|4.SpringCloud 整合security.实现认证中心
- Spring Security入门(三): 基于自定义数据库查询的认证实战
- Spring Security 自定义资源服务器实践
- Spring框架:第六章:注解功能
- 解释spring框架中bean的生命周期_Spring bean的生命周期
- Spring与SpringBoot
- 技术分享 | Spring Boot 异常处理
- Spring Security 里的 HttpSecurity 类
- Spring Boot 3 升级 踩坑笔记
- 《Spring核心技术》第7章:深度解析@DependsOn注解
- Spring Security 实战干货:OAuth2登录获取Token的核心逻辑
- Spring Cloud Security与Spring Cloud的集成示例
- Spring Cloud Security配置JWT和OAuth2的集成实现单点登录-示例
- Spring Security 的核心组件UserDetailsService(二)
- Spring Security用户认证和授权(一)
- 事务隔离属性、spring传播属性、 @Transactional注解详解数据库
- Spring Boot(一):入门篇详解编程语言
- spring boot 接口返回值去掉为null的字段详解编程语言
- spring使用Spring整合Redis和Jedis构建高性能应用(redisjedis与)