SpringBoot整合SpringSecurity(通俗易懂) 1

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: SpringBoot整合SpringSecurity(通俗易懂)

先看后赞,养成习惯。

点赞收藏,人生辉煌。

基于数据库的身份认证

一、创建项目

创建一个 SpringBoot 模块项目,选择相关依赖:

先搭建项目正常访问,在pom.xml中,先把Spring Security依赖注释

<!--<dependency>-->
    <!--<groupId>org.springframework.boot</groupId>-->
    <!--<artifactId>spring-boot-starter-security</artifactId>-->
<!--</dependency>-->

在MySQL数据库中创建一张用户表,id主键自增,并添加两个用户如下:

代码:

创建entity实体

@Data
public class UserInfo {
    private int id;
    private String username;
    private String password;
    private String role;
}

创建mapper接口

@Mapper
@Repository
public interface UserInfoMapper {
    @Select("select * from user where username = #{username}")
    UserInfo getUserInfoByUsername(String username);
}
创建UserInfoService.java文件
@Service
public class UserInfoService {
    @Autowired
    private UserInfoMapper userInfoMapper;
    public UserInfo getUserInfo(String username){
        return userInfoMapper.getUserInfoByUsername(username);
    }
}

创建HelloController.java文件

@RestController
public class HelloController {
    @Autowired
    private UserInfoService userInfoService;
    @GetMapping("/get-user")
    public UserInfo getUser(@RequestParam String username){
        return userInfoService.getUserInfoByUsername(username);
    }
}

配置文件application.yml中设置MySQL连接配置和MyBatis配置

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/security?useSSL=FALSE&serverTimezone=UTC
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
logging:
  level:
    com.example.bdatabaserole.mapper: debug  # 打印sql语句

以上配置好后,启动项目,访问localhost:8080/get-user?username=user,正常获取到用户信息:

下面开始使用Spring Security安全验证:

二、Spring Security基于数据库认证

把pom.xml中的Spring Security依赖注释去掉:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

要从数据库读取用户信息进行身份认证,需要新建类实现UserDetailService接口重写loadUserByUsername方法:

@Component
public class CustomUserDetailsService implements UserDetailsService {
    @Autowired
    private UserInfoService userInfoService;
    /**
     * 需新建配置类注册一个指定的加密方式Bean,或在下一步Security配置类中注册指定
     */
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 通过用户名从数据库获取用户信息
        UserInfo userInfo = userInfoService.getUserInfo(username);
        if (userInfo == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        // 得到用户角色
        String role = userInfo.getRole();
        // 角色集合
        List<GrantedAuthority> authorities = new ArrayList<>();
        // 角色必须以`ROLE_`开头,数据库中没有,则在这里加
        authorities.add(new SimpleGrantedAuthority("ROLE_" + role));
        return new User(
                userInfo.getUsername(),
             // 因为数据库是明文,所以这里需加密密码
                passwordEncoder.encode(userInfo.getPassword()),
                authorities
        );
    }
}

创建Security的配置类WebSecurityConfig继承WebSecurityConfigurerAdapter,并重写configure(auth)方法:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private MyUserDatailService userDatailService;
    /**
     * 指定加密方式
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        // 使用BCrypt加密密码
        return new BCryptPasswordEncoder();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
         auth
                 // 从数据库读取的用户进行身份认证
                .userDetailsService(userDatailService)
                .passwordEncoder(passwordEncoder());
    }
}

上面设置完后,重新启动,在登录页面就可以输入数据库中的用户名/密码了。

三、角色访问控制

上面设置后,可以使用数据库中的用户名/密码登录,还获取到了用户的角色。通过用户的角色,可以限制用户的请求访问:

开启方法的访问权限,需要在WebSecurityConfig添加

@EnableGlobalMethodSecurity注解
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法级安全验证
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    ...
}

修改UserController.java类,增加方法的访问权限

@RestController
public class HelloController {
    @Autowired
    private UserInfoService userInfoService;
    @GetMapping("/get-user")
    public UserInfo getUser(@RequestParam String username){
        return userInfoService.getUserInfo(username);
    }
    @PreAuthorize("hasAnyRole('user')") // 只能user角色才能访问该方法
    @GetMapping("/user")
    public String user(){
        return "user角色访问";
    }
    @PreAuthorize("hasAnyRole('admin')") // 只能admin角色才能访问该方法
    @GetMapping("/admin")
    public String admin(){
        return "admin角色访问";
    }
}

配置完后,重新启动程序,在登录页面中:

输入user/user123登录,该用户角色为user,可以访问localhost:8080/user,不能访问localhost:8080/admin

再重启程序输入admin/admin123登录,角色为admin,能访问localhost:8080/admin,不能访问localhost:8080/user。

四、密码加密保存

前面的用户密码都是手动添加的,所以数据库中是明文显示,在实际开发中,都是需要加密保存的。

下面模拟简单注册用户,加密保存密码:

UserInfoMapper.java类中添加插入用户

@Mapper
@Repository
public interface UserMapper {
 ...
    // 插入用户
    @Insert("insert into user(username, password, role) value(#{username}, #{password}, #{role})")
    int insertUserInfo(UserInfo userInfo);
}

UserInfoService.java类中添加插入方法,注意要加密密码

@Service
public class UserInfoService {
    ...
    @Autowired
    private PasswordEncoder passwordEncoder;
    ...
    public int insertUser(UserInfo userInfo){
        // 加密密码
        userInfo.setPassword(passwordEncoder.encode(userInfo.getPassword()));
        return userInfoMapper.insertUserInfo(userInfo);
    }

}

修改HelloController.java,增加添加用户接口

@RestController
public class HelloController {
    ...
    @PostMapping("/add-user")
    public int addUser(@RequestBody UserInfo userInfo){
        return userInfoService.insertUser(userInfo);
    }
}

配置完后,启动服务,使用Postman发送POST请求来添加用户:

点击Send按钮后,添加失败,不会返回成功1,看到红框的状态码显示401 Unauthorized,说明无权限,需要登录,但注册用户是不用登录的,所以就需要注册用户的请求无需身份验证:

修改WebSecurityConfig配置类,重写configure(HttpSecurity http)方法,配置允许注册用户的请求访问:

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 ...    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers(HttpMethod.POST, "/add-user").permitAll() // 允许post请求/add-user,而无需认证
                .anyRequest().authenticated() // 所有请求都需要验证
                .and()
                .formLogin() // 使用默认的登录页面
                .and()
                .csrf().disable();// post请求要关闭csrf验证,不然访问报错;实际开发中开启,需要前端配合传递其他参数
    }
}

配置允许POST请求/add-user访问后,再在Postman发送请求就可以成功了:

图片

查看数据库数据,添加的用户密码已加密:

使用加密密码登录,需要修改CustomUserDetailsService类,之前从数据库拿到明文密码后需要加密,现在数据库里面的密码已经加密了,就不用加密了:

@Component
public class MyUserDatailService implements UserDetailsService {
    //@Autowired
    //private PasswordEncoder passwordEncoder;
    ...
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        ...
        return new User(
                user.getUsername(),
                // 数据库密码已加密,不用再加密
                user.getPassword(),
                authorities
        );
    }
}

浏览器访问localhost:8080/user,输入zeng/zeng123登录即可。

目录
相关文章
|
6月前
|
存储 安全 Java
Spring Boot整合Spring Security--学习笔记
Spring Boot整合Spring Security--学习笔记
102 1
|
6月前
|
安全 数据安全/隐私保护
Springboot+Spring security +jwt认证+动态授权
Springboot+Spring security +jwt认证+动态授权
209 0
|
1月前
|
安全 Java 关系型数据库
springboot整合springsecurity,从数据库中认证
本文介绍了如何在SpringBoot应用中整合Spring Security,并从数据库中进行用户认证的完整步骤,包括依赖配置、数据库表创建、用户实体和仓库接口、用户详情服务类、安全配置类、控制器类以及数据库初始化器的实现。
108 3
springboot整合springsecurity,从数据库中认证
|
3月前
|
NoSQL 关系型数据库 MySQL
SpringBoot 集成 SpringSecurity + MySQL + JWT 附源码,废话不多直接盘
SpringBoot 集成 SpringSecurity + MySQL + JWT 附源码,废话不多直接盘
150 2
|
3月前
|
安全 Java 数据安全/隐私保护
基于SpringBoot+Spring Security+Jpa的校园图书管理系统
本文介绍了一个基于SpringBoot、Spring Security和JPA开发的校园图书管理系统,包括系统的核心控制器`LoginController`的代码实现,该控制器处理用户登录、注销、密码更新、角色管理等功能,并提供了系统初始化测试数据的方法。
60 0
基于SpringBoot+Spring Security+Jpa的校园图书管理系统
|
3月前
|
安全 Java 数据库
|
3月前
|
JSON 安全 Java
|
3月前
|
安全 Java 关系型数据库
SpringBoot SpringSecurity 介绍(基于内存的验证)
SpringBoot SpringSecurity 介绍(基于内存的验证)
44 0
|
5月前
|
Java 数据库
Springboot集成SpringSecurity有源码
Springboot集成SpringSecurity有源码
|
6月前
|
前端开发 JavaScript Java
基于Springboot+SpringSecurity+Activiti7实现的工作流系统可方便二次开发(附完整源码)
基于Springboot+SpringSecurity+Activiti7实现的工作流系统可方便二次开发(附完整源码)
208 0

热门文章

最新文章

下一篇
无影云桌面