01-快速体验SpringSecurity5.7.2|权限管理基础

博客 分享
0 137
张三
张三 2022-08-29 16:03:45
悬赏:0 积分 收藏

01 - 快速体验 Spring Security 5.7.2 | 权限管理基础

 01 - 快速体验 Spring Security 5.7.2 | 权限管理基础 文章就使用 Spring Security 实现用户认证和授权。

在前面 SpringBoot 2.7.2 的系列文章中,已经创建了几个 computer 相关的接口,这些接口直接通过 Spring Doc 或 POSTMAN 就可以访问。例如:

GET http://localhost:9099/computer/1

访问该服务可以获取 id 为 1 的电脑详情。

接下来的文章就使用 Spring Security 实现用户认证和授权。

1 添加 Spring Security

1.1 添加依赖

Spring Boot 对 Spring Security 非常友好,它已经管理了 Spring Security 的依赖版本,并且提供 starter 的方式进行整合:

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

1.2 测试服务

添加依赖后重新启动服务,可以在控制台看到输出:

image-20220819161719909

在浏览器中访问该服务,会自动跳转到登录页面,该页面是 Spring Security 默认提供的。浏览器中地址栏自动跳转到:

http://localhost:9099/login

在登录页面,用户名填写 user,密码填写上面控制台中输出的密码,点击“Sign in”,便会进入系统,显示电脑详情。

2 硬编码配置用户名和密码

咱们使用的 Spring Boot 版本是 2.7.2,对应的 Spring Security 版本为 5.7.2,从 5.7 开始,Spring Security 的使用有一些改变,其中之一就是配置 Security 时不推荐继承 WebSecurityConfigurerAdapter 类。

上面的 demo 中使用的用户名是 user,密码是在启动中生成的,这肯定不符合开发的需求。配置用户名密码有三种方式:

  1. 在配置文件 application.yml 中写死用户名和密码;
  2. 定义配置类,在该方法中写死用户名密码;
  3. 实现 UserDetailsService 接口,然后定义配置类进行配置。

前面两者在 demo 中玩玩就行。

2.1 在配置文件中配置用户名密码

这种方式比较简单,直接在 application.yml 中配置即可:

spring:  profiles:    active: @env@  security:    user:      name: hero1      password: '111111'      roles: 'admin'

2.2 在内存中配置用户名密码

删除上面的 security 节点相关的配置,使用配置文件,配置在内存中生效的用户名密码。

创建配置类 SecurityConfig:

package com.yygnb.demo.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.core.userdetails.User;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.crypto.password.PasswordEncoder;import org.springframework.security.provisioning.InMemoryUserDetailsManager;@Configurationpublic class SecurityConfig {    @Bean    public PasswordEncoder passwordEncoder() {        return new BCryptPasswordEncoder();    }    @Bean    public InMemoryUserDetailsManager userDetailsService() {        UserDetails user = User.builder()                .username("hero2")                .password(passwordEncoder().encode("111111"))                .roles("admin")                .build();        return new InMemoryUserDetailsManager(user);    }}

重启服务,登录界面输入 hero2/111111 进行测试。

这种方式也是写死的用户名密码,在实际开发中不会使用的。所以,先删除这个文件,然后再继续后面的学习。

3 数据库配置用户名和密码

在开始这个部分之前,请确保删除了上面编写的 SecurityConfig。

3.1 数据库表

首先需要定义表结构。

由于我这里是基于前面 spring boot 2.7.2 系列文章的demo进行的,我继续沿用 Liquibase 的方式定义表结构。尊敬的读者们可以从 GitHub 上获取 demo 基础工程,也可以联系我获取,还可以脱离 demo 基础工程,自己用习惯的方式创建数据库表结构,如 SQL 语句、图形化界面等。

resources/db/demo/ 目录中创建文件 demo-changelog-v2.xml,该文件用来定义这次数据库的变更。

<?xml version="1.0" encoding="UTF-8"?><databaseChangeLog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"                   xmlns="http://www.liquibase.org/xml/ns/dbchangelog"                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog                    https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">    <changeSet id="T100-20220801-yyg-025" author="yyg">        <createTable remarks="用户表" tableName="user">            <column autoIncrement="true" name="id" type="BIGINT">                <constraints nullable="false" primaryKey="true"/>            </column>            <column name="username" remarks="用户名" type="VARCHAR(32)">                <constraints nullable="false"/>            </column>            <column name="password" remarks="密码" type="VARCHAR(128)">                <constraints nullable="false"/>            </column>            <column name="name" remarks="姓名" type="VARCHAR(32)">                <constraints nullable="false"/>            </column>        </createTable>        <addAutoIncrement tableName="user" columnName="id" columnDataType="BIGINT"                          incrementBy="1" startWith="1"/>        <insert tableName="user">            <column name="id" valueNumeric="1"/>            <column name="username" value="hero1"/>            <column name="password" value="111111"/>            <column name="name" value="HERO 1"/>        </insert>        <insert tableName="user">            <column name="id" valueNumeric="2"/>            <column name="username" value="hero2"/>            <column name="password" value="222222"/>            <column name="name" value="HERO 2"/>        </insert>        <insert tableName="user">            <column name="id" valueNumeric="3"/>            <column name="username" value="hero3"/>            <column name="password" value="333333"/>            <column name="name" value="HERO 3"/>        </insert>    </changeSet></databaseChangeLog>

该文件定义了 user 表并插入了三条数据,user 表只有四个字段:id 主键、用户名、密码、姓名,主键自增长。

重启服务,会自动生成表结构。

3.2 生成实体类

可以通过逆向工程生成,可以复制下面的代码。

com.yygnb.demo.entity.User

/** * 用户表 */@Schema(title = "用户")@Data@NoArgsConstructor@AllArgsConstructor@Builderpublic class User implements Serializable {    private static final long serialVersionUID = 1L;    @TableId(value = "id", type = IdType.AUTO)    private Long id;    @Schema(title = "用户名")    @NotNull(message = "不能为空")    private String username;    @Schema(title = "密码")    @NotNull(message = "不能为空")    private String password;    @Schema(title = "姓名")    private String name;}

3.3 Mapper

com.yygnb.demo.mapper.UserMapper

public interface UserMapper extends BaseMapper<User> {}

resources/mapper/UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.yygnb.demo.mapper.UserMapper"></mapper>

到这一步,准备工作就完成了,接下来继续回到 Spring Security。

3.4 PasswordEncoder

Spring Security 中在认证授权时,需要 PasswordEncoder 对象,该对象可以对密码加密。

com.yygnb.demo.config.PasswordEncoderConfig

@Configurationpublic class PasswordEncoderConfig {    @Bean    public PasswordEncoder passwordEncoder() {        return new BCryptPasswordEncoder();    }}

3.5 实现 UserDetailsService 接口

Spring Security 提供了一个接口:UserDetailsService 。该接口只有一个方法 loadUserByUsername,在该方法中就可以查询数据库,根据用户名查询用户信息了。该方法返回 UserDetails。UserDetails 是一个接口,Spring Security 提供了一个实现类 User。

创建类:UserDetailsServiceImpl,实现 UserDetailsService 接口,并添加 @Service 注解。

com.yygnb.demo.service.impl.UserDetailsServiceImpl

package com.yygnb.demo.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.yygnb.demo.entity.User;import com.yygnb.demo.mapper.UserMapper;import lombok.RequiredArgsConstructor;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.authority.AuthorityUtils;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.core.userdetails.UsernameNotFoundException;import org.springframework.security.crypto.password.PasswordEncoder;import org.springframework.stereotype.Service;import java.util.List;@RequiredArgsConstructor@Servicepublic class UserDetailsServiceImpl implements UserDetailsService {    //    @Autowired    private final PasswordEncoder passwordEncoder;    private final UserMapper userMapper;    @Override    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {        QueryWrapper<User> wrapper = new QueryWrapper<>();        wrapper.eq("username", username);        User user = this.userMapper.selectOne(wrapper);        if (user == null) {            throw new UsernameNotFoundException("根据用户名未查询到用户");        }        // 模拟查询权限        List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("admin");        return new org.springframework.security.core.userdetails.User(                user.getUsername(), passwordEncoder.encode(user.getPassword()), authorities);    }}

如果是以前版本的 Spring Security,还需要定义配置继承自 WebSecurityConfigurerAdapter 类,重写 config 方法,并在该方法中设置 UserDetailsService 等。现在的版本不需要这些无聊的操作了。

重启服务,访问测试。

感谢你阅读本文,如果本文给了你一点点帮助或者启发,还请三连支持一下,点赞、关注、收藏,作者会持续与大家分享更多干货

posted @ 2022-08-29 15:29 程序员优雅哥(\/同) 阅读(10) 评论(0) 编辑 收藏 举报
回帖
    张三

    张三 (王者 段位)

    821 积分 (2)粉丝 (41)源码

     

    温馨提示

    亦奇源码

    最新会员