赞
踩
安全对于任何系统来说都是非常重要的,权限的分配和管理一直都是开发者需要特别重视的。一旦缺乏基本和有力的授权验证,一些别有用心之人就会利用这个漏洞对开发者的 Web 应用或者其他软件进行不法侵害。Spring Boot 技术中有许多优秀的安全框架和认证授权方案,本次将介绍比较流行的框架技术 Spring Security 及其实践应用。
Spring Security 是 Spring Boot 中一款功能强大基于 Spring 的企业级应用的提供安全访问权限的安装框架,在实际工程项目中也会经常用到。通过依赖注入的方式,可以使用 Spring Security 库提供声明式的安全访问控制功能。它和 Spring Boot 以及其他 Spring 模块紧密相连。
Spring Security 的原理其实就是一个过滤器链,内部包含了提供各种功能的过滤器。
图中只展示了核心过滤器,其它的非核心过滤器并没有在图中展示
通过 debug 查看当前的过滤器链。
package org.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class Main {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(Main.class, args);
System.out.println(run);//在此处打上断点
}
}
打开表达式计算面板
run.getBean(DefaultSecurityFilterChain.class)
计算求值:
SecurityContextHolder.getContext();
安装,在 pom.xml 中导入依赖即可
org.springframework.boot spring-boot-starter-security在项目中编写一个测试的接口 /testHi,代码如下:
package org.example.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HiController {
@GetMapping(“/hi”)
public String hi(){
return “Hi”;
}
}
编写一个类,更好的配置管理。
package org.example.config;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
/**
最后运行会出现如下界面:
如果想要修改默认的账号和密码,可以在 application.properties 文件中加入下面的配置项。
spring.security.user.name=freejava
spring.security.user.password=123456
spring.security.user.roles[]=admin
所谓内存认证就是自定义配置类,该配置类继承 WebSecurityConfigurerAdapter,需要实现一些自定义配置和方法,具体代码如下:
package org.example.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.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;
@EnableWebSecurity
public class RealSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
PasswordEncoder passwordEncoder(){
//NoOpPasswordEncoder 在高版本的Spring Boot 中已被弃用,不建议使用
return new BCryptPasswordEncoder();
}
@Autowired PasswordEncoder passwordEncoder;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.passwordEncoder(passwordEncoder)//使用对应的加密
.withUser(“admin”)
.password(passwordEncoder.encode(“123456”))//使用对应的解密
.roles(“ADMIN”,“USER”)
.and()
.withUser(“freephp”)
.password(passwordEncoder.encode(“123456”))
.roles(“USER”);
}
}
上面这段代码中,inMemoryAuthentication 代表把这个配置保存在内存中,然后使用 withUser 方法增加授权账号,用 password 方法设置密码,用 roles 来设置账号所属的权限群组。
而 HttpSecurity 是另外一种认证方式,也是使用 configure 方法,具体代码如下:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(“/admin/“)
.hasRole(“ADMIN”)
.antMatchers(”/user/”)
.access(“hasAnyRole(‘ADMIN’,‘USER’)”)
.anyRequest()
.authenticated()//任意登录的用户都可以访问
.and()
.formLogin()
.loginProcessingUrl(“/login”)
.permitAll()
.and()
.csrf()
.disable();
}
使用 andMatcher 设置需要被授权的 URL 路径,access 方法给予某些角色访问权限,代码如下:。
package org.example.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SwagController {
@GetMapping(“/user/sayHi”)
public String myUser(){
return “Hi,user”;
}
@GetMapping(“/admin/hello”)
public String admin(){
return “admin page”;
}
@GetMapping(“/hello”)
public String hello(){
return “hello,man”;
}
}
运行项目后,访问 http://localhost:8080/admin/hello, 则会要求输入账号和密码,使用 admin 账号,密码输入 123456,即可进入后台 /admin/hello 页面,如图。
- Authentication接口: 它的实现类,表示当前访问系统的用户,封装了用户相关信息。
- AuthenticationManager接口: 定义了认证Authentication的方法。
- UserDetailsService接口: 加载用户特定数据的核心接口。里面定义了一个根据用户名查询用户信息的方法。
- UserDetails接口: 提供核心用户信息。通过UserDetailsService根据用户名获取处理的用户信息要封装成UserDetails对象返回,然后将这些信息封装到Authentication对象中。
所以接下来如果要使用数据库做登录验证,只要把实现类 InMemoryUserDetailsManager 做一个替换,DaoAuthenticationProvider 调用自定义的实现类。让其不再使用内存做认证进入数据库查询,实现 UserDetailsService 接口即可。
之前都是使用内存来存储认证数据,其实可以考虑使用数据库进行持久化数据存储。这样更加方便进行账号管理,也更符合实际项目开发的需求。
创建一个 roles 库,然后创建用户表、角色权限表、用户和角色权限关系表。
create database r_security;
use r_security;
– 用户表
CREATE TABLE r_users
(
id
int(11) unsigned NOT NULL AUTO_INCREMENT primary key COMMENT ‘主键’,
username
varchar(50) not null comment ‘账号名’,
password
varchar(300) not null comment ‘密码’,
status
tinyint(11) not null comment ‘账号状态,1:正常、2:被封’,
created
int (11) not null comment ‘创建时间,时间戳’
);
– 角色权限表
create table r_roles
(
id
int(11) unsigned not null auto_increment comment ‘主键’,
name
varchar(50) not null comment ‘角色名’,
permission_path
varchar(500) not null comment ‘权限路径,如/admin/*’,
primary key (id)
);
– 用户角色权限关系表
create table r_user_roles
(
id
int(11) unsigned not null auto_increment comment ‘主键’,
user_id
int(11) unsigned not null comment ‘用户ID’,
role_id
int(11) unsigned not null comment ‘角色ID’,
primary key (id
),
key user_id
(user_id
),
key role_id
(role_id
),
constraint role_id
foreign key (role_id
) references r_roles
(id
) on
delete restrict ,
constraint user_id
foreign key (user_id
) references r_users
(id
) on
delete restrict
)
为了方便测试,先插入几条测试数据,r_users 的数据如图
R_roles的数据如图,插入三条数据,有三种角色,一是管理员角色,二是 root 权限,也就是超级管理员。三是 dba,数据管理员。这三种角色可以访问不同的 URL。
用户角色表中插入数据
为了生成上面 r_users 表中加密后的密码,攥写了使用 Bcrypt 加密的程序,代码如下:
import java.util.ArrayList;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
public class BcryptTest {
public static void main(String[] args) {
ArrayList passwordArr = new ArrayList<>();
passwordArr.add(“123456”);
getUsersEncodePasswords(passwordArr);
}
private static void getUsersEncodePasswords(ArrayList passwordArr) {
for (String pass :passwordArr){
//密码加密
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String newPassword = passwordEncoder.encode(pass);
System.out.println(" 原始密码是:“+pass+”,加密密码为:"+newPassword);
//对比这两个密码是不是同一个密码
boolean match = passwordEncoder.matches(pass,newPassword);
System.out.println(“两个密码一致:”+match);
}
}
}
运行结果如图:
Bcrpt 加密算法非常安全,此算法自身实现了随机盐生成,很难被逆向破解。
创建一个新的项目,导入依赖,pom.xml代码如下:
<?xml version="1.0" encoding="UTF-8"?>
4.0.0
org.example
Security2
1.0-SNAPSHOT
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注网络安全获取)
还有兄弟不知道网络安全面试可以提前刷题吗?费时一周整理的160+网络安全面试题,金九银十,做网络安全面试里的显眼包!
王岚嵚工程师面试题(附答案),只能帮兄弟们到这儿了!如果你能答对70%,找一个安全工作,问题不大。
对于有1-3年工作经验,想要跳槽的朋友来说,也是很好的温习资料!
【完整版领取方式在文末!!】
93道网络安全面试题
内容实在太多,不一一截图了
最后给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
同时每个成长路线对应的板块都有配套的视频提供:
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
伙伴们一点帮助!
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
同时每个成长路线对应的板块都有配套的视频提供:
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-OqMx6v7M-1712548572010)]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。