SpringBoot搭建Spring Security 入门
原文链接
简介
Spring Security 是一个提供身份验证,授权,保护以及防止常见攻击的框架,由于同时支持响应式和命令式,是spring框架的安全标准。
前提条件
jdk1.8+
例子使用SpringBoot版本 【2.0.5.RELEASE】,代码都是简写,只写关键代码,源码demo,文章底部github
引入maven jar包(正常添加jar包依赖,只需保留第一步的jarbao,第三步第四步忽略即可)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
因为SpringBoot提供了BOM来管理版本,因此不需要指定版本,如果我们需要指定版本可以通过配置maven属性来配置
例
<properties>
<!-- ... -->
<spring-security.version>5.2.2.BUILD-SNAPSHOT</spring-security.version>
</dependencies>
- 如果使用SNAPSHOT版本则需要定义Spring Snapshot存储库
<repositories>
<!-- ... possibly other repository elements ... -->
<repository>
<id>spring-snapshot</id>
<name>Spring Snapshot Repository</name>
<url>https://repo.spring.io/snapshot</url>
</repository>
</repositories>
- 如果使用里程碑版本或者候选的版本,则需要指定Spring Milestone存储库
<repositories>
<!-- ... possibly other repository elements ... -->
<repository>
<id>spring-milestone</id>
<name>Spring Milestone Repository</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
- application.properties 配置属性内容
# 启动端口
server.port=8081
# 启动项目路径
server.servlet.context-path=/simple-security
-
此时简单版的demo就已经完成了,访问http://127.0.0.1:8081会重定向到http://127.0.0.1:8081/simple-security/login 页面显示内容如下
-
默认的用户名:user,密码为控制台打印的uuid
8.此时我们输入用户名密码之后验证通过了,但是会显示404,这是因为我们没有配置登录成功的首页,现在开始配置首页
9.新建一个WebSecurityConfig配置类,继承
WebSecurityConfigurerAdapter,此处配置关闭了csrf,支持表单登录,
拦截/login登录的请求,登录成功跳转login-success
代码如下
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 屏蔽csrf跨站
http.csrf().disable()
// 支持表单登录
.formLogin()
// 登录逻辑处理url
.loginProcessingUrl("/login")
// 登录页面
// .loginPage("login-view")
//自定义成功登录页面
.successForwardUrl("/login-success");
}
/**
* 密码验证方式
* NoOpPasswordEncoder.getInstance() 字符串校验
* @return
*/
@Bean
public PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
}
- 配置一个WebMvcConfig,重定向我们的url,实现登录逻辑处理
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("redirect:/login");
}
}
- 编写一个controller,作为登录成功之后的跳转
@RestController
public class LoginController {
@RequestMapping("/login-success")
public String login(){
return "login success";
}
}
12.此时启动项目,访问http://127.0.0.1:8081/simple-security/login,输入用户名user,密码(控制台打印的uuid)登录成功即可看到打印的login success
- 自定义用户,实现UserDetailsService,此处我们生成的用户名是tz,密码就是123,我们实际使用中,可以根据用户名在数据库中查找返回,此处为了方便直接设置了一下,没有进行数据库查询。这样我们就成功配置了一个用户名tz密码123的账号,现在就来登录试一下吧
@Service
public class MyUserDetailService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserDetails userDetails = User.withUsername("tz").password("123").build();
return userDetails;
}
}
14.浏览器打开输入http://127.0.0.1:8081/simple-security/login
账号tz,密码123,点击login,登录成功跳转到我们刚才定义的controller,密码太简单了,我们平常不能直接使用明文密码啊,一般都是加密的,先看上面的WebSecurityConfig中我们定义了
PasswordEncoder的Bean 我们返回了一个
NoOpPasswordEncoder.getInstance()
这个代表进行简单的字符串匹配,也就是字符串相等就OK,我们下面配置另一个加密,BCryptPasswordEncoder(),修改我们的WebSecurityConfig
/**
* 密码验证方式
* NoOpPasswordEncoder.getInstance() 字符串校验
* @return
*/
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
15.新建一个test类,生成我们的Bcrypt加密的密码,方便一会我们测试
@SpringBootTest
public class SimpleSecurityApplicationTests {
@Test
public void contextLoads() {
String hashpw = BCrypt.hashpw("123", BCrypt.gensalt());
System.out.println(hashpw);
}
// 打印结果 $2a$10$pTffBwh9mawjeGG9K5ZhbenBfWQRV1aFVgZqVt59eM67iJhDqARyG
// 这个字符串就代表123,上面我们是使用的随机盐的方式,每次生成的密码都不一样,但是校验时原密码都是123
}
下面把打印的结果替换到我们的MyUserDetailService中
修改结果如下
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
UserDetails userDetails = User.withUsername("tz").password("$2a$10$pTffBwh9mawjeGG9K5ZhbenBfWQRV1aFVgZqVt59eM67iJhDqARyG").build();
return userDetails;
}
- 启动项目,继续使用用户tz密码123登录,此时也是显示登录成功
- 下面展示一下基本的授权
Controller中新增资源url
@RequestMapping("/r/r1")
public String r1(){
return "r1";
}
@RequestMapping("/r/r2")
public String r2(){
return "r2";
}
WebSecurityConfig增加对资源的拦截,此处访问/r/r1需要p1权限,访问/r/r2需要p2权限
// 屏蔽csrf跨站
http.csrf().disable()
.authorizeRequests()
// 拦截/r/**请求需要认证
.antMatchers("/r/r1").hasAuthority("p1")
.antMatchers("/r/r2").hasAuthority("p2")
.antMatchers("/r/**").authenticated()
// // 除了/r/** 其他都可以访问
.anyRequest().permitAll()
.and()
// 支持表单登录
.formLogin()
// 登录逻辑处理url
.loginProcessingUrl("/login")
//自定义成功登录页面
.successForwardUrl("/login-success");
}
MyUserDetailService中给tz用户增加p1权限
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
UserDetails userDetails = User.withUsername("tz").password("$2a$10$pTffBwh9mawjeGG9K5ZhbenBfWQRV1aFVgZqVt59eM67iJhDqARyG").authorities("p1").build();
return userDetails;
}
18.此时基本的权限拦截就完成了,如需更复杂的请参考官网验证,下面演示一下浏览器访问http://127.0.0.1:8081/simple-security/login使用用户名tz密码123来进行登录
修改为r1的访问url,访问查看我们 已经读取到r1 的资源
修改为r2的访问URL,访问查看我们已经被拒绝,显示403,因为我们只有p1权限,访问r1需要p1权限,所以我们可以访问,访问r2需要p2权限,我们没有p2权限,所以拒绝我们的访问
19. 好了入门教程到此结束了,如有错误欢迎指出
github demo地址 https://github.com/TianPuJun/springboot-demo/tree/master/springboot-simple-security
官网 https://spring.io/projects/spring-security
参考https://docs.spring.io/spring-security/site/docs/5.2.2.BUILD-SNAPSHOT/reference/htmlsingle/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!