Spring Boot中使用 Spring Security 构建权限系统的示例代码
发布时间 - 2026-01-11 02:46:18 点击率:次Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

权限控制是非常常见的功能,在各种后台管理里权限控制更是重中之重.在Spring Boot中使用 Spring Security 构建权限系统是非常轻松和简单的.下面我们就来快速入门 Spring Security .在开始前我们需要一对多关系的用户角色类,一个restful的controller.
参考项目代码地址
- 添加 Spring Security 依赖
首先我默认大家都已经了解 Spring Boot 了,在 Spring Boot 项目中添加依赖是非常简单的.把对应的spring-boot-starter-*** 加到pom.xml文件中就行了
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
- 配置 Spring Security
简单的使用 Spring Security 只要配置三个类就完成了,分别是:
UserDetails
这个接口中规定了用户的几个必须要有的方法
public interface UserDetails extends Serializable {
//返回分配给用户的角色列表
Collection<? extends GrantedAuthority> getAuthorities();
//返回密码
String getPassword();
//返回帐号
String getUsername();
// 账户是否未过期
boolean isAccountNonExpired();
// 账户是否未锁定
boolean isAccountNonLocked();
// 密码是否未过期
boolean isCredentialsNonExpired();
// 账户是否激活
boolean isEnabled();
}
UserDetailsService
这个接口只有一个方法 loadUserByUsername,是提供一种用 用户名 查询用户并返回的方法。
public interface UserDetailsService {
UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}
WebSecurityConfigurerAdapter
这个内容很多,就不贴代码了,大家可以自己去看.
我们创建三个类分别继承上述三个接口
此 User 类不是我们的数据库里的用户类,是用来安全服务的.
/**
* Created by Yuicon on 2017/5/14.
*/
public class User implements UserDetails {
private final String id;
//帐号,这里是我数据库里的字段
private final String account;
//密码
private final String password;
//角色集合
private final Collection<? extends GrantedAuthority> authorities;
User(String id, String account, String password, Collection<? extends GrantedAuthority> authorities) {
this.id = id;
this.account = account;
this.password = password;
this.authorities = authorities;
}
//返回分配给用户的角色列表
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@JsonIgnore
public String getId() {
return id;
}
@JsonIgnore
@Override
public String getPassword() {
return password;
}
//虽然我数据库里的字段是 `account` ,这里还是要写成 `getUsername()`,因为是继承的接口
@Override
public String getUsername() {
return account;
}
// 账户是否未过期
@JsonIgnore
@Override
public boolean isAccountNonExpired() {
return true;
}
// 账户是否未锁定
@JsonIgnore
@Override
public boolean isAccountNonLocked() {
return true;
}
// 密码是否未过期
@JsonIgnore
@Override
public boolean isCredentialsNonExpired() {
return true;
}
// 账户是否激活
@JsonIgnore
@Override
public boolean isEnabled() {
return true;
}
}
继承 UserDetailsService
/**
* Created by Yuicon on 2017/5/14.
*/
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
// jpa
@Autowired
private UserRepository userRepository;
/**
* 提供一种从用户名可以查到用户并返回的方法
* @param account 帐号
* @return UserDetails
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String account) throws UsernameNotFoundException {
// 这里是数据库里的用户类
User user = userRepository.findByAccount(account);
if (user == null) {
throw new UsernameNotFoundException(String.format("没有该用户 '%s'.", account));
} else {
//这里返回上面继承了 UserDetails 接口的用户类,为了简单我们写个工厂类
return UserFactory.create(user);
}
}
}
UserDetails 工厂类
/**
* Created by Yuicon on 2017/5/14.
*/
final class UserFactory {
private UserFactory() {
}
static User create(User user) {
return new User(
user.getId(),
user.getAccount(),
user.getPassword(),
mapToGrantedAuthorities(user.getRoles().stream().map(Role::getName).collect(Collectors.toList()))
);
}
//将与用户类一对多的角色类的名称集合转换为 GrantedAuthority 集合
private static List<GrantedAuthority> mapToGrantedAuthorities(List<String> authorities) {
return authorities.stream()
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
}
}
重点, 继承 WebSecurityConfigurerAdapter 类
/**
* Created by Yuicon on 2017/5/14.
*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// Spring会自动寻找实现接口的类注入,会找到我们的 UserDetailsServiceImpl 类
@Autowired
private UserDetailsService userDetailsService;
@Autowired
public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
// 设置UserDetailsService
.userDetailsService(this.userDetailsService)
// 使用BCrypt进行密码的hash
.passwordEncoder(passwordEncoder());
}
// 装载BCrypt密码编码器
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
//允许跨域
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*")
.allowedMethods("GET", "HEAD", "POST","PUT", "DELETE", "OPTIONS")
.allowCredentials(false).maxAge(3600);
}
};
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// 取消csrf
.csrf().disable()
// 基于token,所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
// 允许对于网站静态资源的无授权访问
.antMatchers(
HttpMethod.GET,
"/",
"/*.html",
"/favicon.ico",
"/**/*.html",
"/**/*.css",
"/**/*.js",
"/webjars/**",
"/swagger-resources/**",
"/*/api-docs"
).permitAll()
// 对于获取token的rest api要允许匿名访问
.antMatchers("/auth/**").permitAll()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated();
// 禁用缓存
httpSecurity.headers().cacheControl();
}
}
- 控制权限到 controller
使用 @PreAuthorize("hasRole('ADMIN')") 注解就可以了
/**
* 在 @PreAuthorize 中我们可以利用内建的 SPEL 表达式:比如 'hasRole()' 来决定哪些用户有权访问。
* 需注意的一点是 hasRole 表达式认为每个角色名字前都有一个前缀 'ROLE_'。所以这里的 'ADMIN' 其实在
* 数据库中存储的是 'ROLE_ADMIN' 。这个 @PreAuthorize 可以修饰Controller也可修饰Controller中的方法。
**/
@RestController
@RequestMapping("/users")
@PreAuthorize("hasRole('USER')") //有ROLE_USER权限的用户可以访问
public class UserController {
@Autowired
private UserRepository repository;
@PreAuthorize("hasRole('ADMIN')")//有ROLE_ADMIN权限的用户可以访问
@RequestMapping(method = RequestMethod.GET)
public List<User> getUsers() {
return repository.findAll();
}
}
- 结语
Spring Boot中 Spring Security 的入门非常简单,很快我们就能有一个满足大部分需求的权限系统了.而配合 Spring Security 的好搭档就是 JWT 了,两者的集成文章网络上也很多,大家可以自行集成.因为篇幅原因有不少代码省略了,需要的可以参考项目代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# spring
# security
# 权限
# boot
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
jimdo怎样用html5做选项卡_jimdo选项卡html5实现与切换效果【指南】
php后缀怎么变mp4格式错误_修改扩展名提示格式不对怎么办【技巧】
猪八戒网站制作视频,开发一个猪八戒网站,大约需要多少?或者自己请程序员,需要什么程序员,多少程序员能完成?
Laravel如何记录自定义日志?(Log频道配置)
Laravel Artisan命令怎么自定义_创建自己的Laravel命令行工具完全指南
专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?
EditPlus中的正则表达式 实战(2)
Laravel如何使用Livewire构建动态组件?(入门代码)
电视网站制作tvbox接口,云海电视怎样自定义添加电视源?
Python企业级消息系统教程_KafkaRabbitMQ高并发应用
香港服务器部署网站为何提示未备案?
如何用PHP快速搭建CMS系统?
高配服务器限时抢购:企业级配置与回收服务一站式优惠方案
laravel怎么配置Redis作为缓存驱动_laravel Redis缓存配置教程
如何用ChatGPT准备面试 模拟面试问答与职场话术练习教程
Laravel事件监听器怎么写_Laravel Event和Listener使用教程
Laravel中间件起什么作用_Laravel Middleware请求生命周期与自定义详解
深圳网站制作培训,深圳哪些招聘网站比较好?
怎么用AI帮你为初创公司进行市场定位分析?
javascript日期怎么处理_如何格式化输出
如何批量查询域名的建站时间记录?
php8.4header发送头信息失败怎么办_php8.4header函数问题解决【解答】
Gemini手机端怎么发图片_Gemini手机端发图方法【步骤】
WordPress 子目录安装中正确处理脚本路径的完整指南
ChatGPT常用指令模板大全 新手快速上手的万能Prompt合集
东莞专业网站制作公司有哪些,东莞招聘网站哪个好?
免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?
香港服务器租用费用高吗?如何避免常见误区?
Laravel如何构建RESTful API_Laravel标准化API接口开发指南
百度浏览器ai对话怎么关 百度浏览器ai聊天窗口隐藏
微博html5版本怎么弄发超话_超话进入入口及发帖格式要求【教程】
如何快速搭建自助建站会员专属系统?
如何用AI帮你把自己的生活经历写成一个有趣的故事?
关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)
Midjourney怎么调整光影效果_Midjourney光影调整方法【指南】
浅谈Javascript中的Label语句
JS弹性运动实现方法分析
Laravel Eloquent:优雅地将关联模型字段扁平化到主模型中
如何快速搭建FTP站点实现文件共享?
Win11怎么关闭资讯和兴趣_Windows11任务栏设置隐藏小组件
夸克浏览器网页跳转延迟怎么办 夸克浏览器跳转优化
Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置
如何安全更换建站之星模板并保留数据?
如何在宝塔面板中修改默认建站目录?
Linux网络带宽限制_tc配置实践解析【教程】
音响网站制作视频教程,隆霸音响官方网站?
如何用wdcp快速搭建高效网站?
香港服务器建站指南:外贸独立站搭建与跨境电商配置流程
如何在万网主机上快速搭建网站?
JavaScript如何实现倒计时_时间函数如何精确控制

