系列七、Spring Security中基于Jdbc的用户认证 & 授权

一、Spring Security中基于Jdbc的用户认证 & 授权

1.1、概述

        前面的系列文章介绍了基于内存定义用户的方式,其实Spring Security中还提供了基于Jdbc的用户认证 & 授权,再说基于Jdbc的用户认证 & 授权之前,不得不说一下Spring Security中一个非常重要的类UserDetailService,关于UserDetailService,请参考【系列二、Spring Security中的核心类】,这里不再赘述。

1.2、JdbcUserDetailsManager

        JdbcUserDetailsManager实现了UserDetailsManager接口,UserDetailsManager继承于UserDetailsService接口,继承结构如下:

系列七、Spring Security中基于Jdbc的用户认证 & 授权_第1张图片

通过这个类可以使用Spring Security内置的Jdbc操作数据库。

1.2.1、sql脚本的位置 

org/springframework/security/core/userdetails/jdbc/users.ddl

系列七、Spring Security中基于Jdbc的用户认证 & 授权_第2张图片

1.2.2、我整理好的 

DROP TABLE IF EXISTS `users`;
create table users(
                      username varchar(50) not null primary key COMMENT '用户名',
                      password varchar(100) not null COMMENT '密码',
                      enabled int not null COMMENT '账户是否启用(1:启用、0:禁用)'
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户表' ROW_FORMAT = DYNAMIC;

DROP TABLE IF EXISTS `authorities`;
create table authorities (
                             username varchar(50) not null COMMENT '用户名',
                             authority varchar(50) not null COMMENT '权限',
                             constraint fk_authorities_users foreign key(username) references users(username)
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '权限表' ROW_FORMAT = DYNAMIC;

create unique index ix_auth_username on authorities (username,authority);

1.3、资源类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2024/1/11 20:58
 * @Description: 测试资源
 */
@RestController
public class HelloController7004 {

    /**
     * 任何人都可以访问
     * @return
     */
    @GetMapping("/helloWorld")
    public R helloWorld() {
        return R.ok().data("Hello World");
    }

    /**
     * 登录后才能访问
     * @return
     */
    @GetMapping("/sayHi")
    public R sayHi() {
        return R.ok().data("嗨!");
    }

    /**
     * 需要具有dba角色的人才能访问
     * @return
     */
    @GetMapping("/dba/helloWorld")
    public R dba() {
        return R.ok().data("dba Hello World");
    }

    /**
     * 需要具有admin角色的人才能访问
     * @return
     */
    @GetMapping("/admin/helloWorld")
    public R admin() {
        return R.ok().data("admin Hello World");
    }

}

1.4、配置类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2024/1/11 21:50
 * @Description: Spring Security配置类
 */
@Configuration
public class MyWebSecurityConfigurerAdapter7004 extends WebSecurityConfigurerAdapter {

    @Resource
    private MyAuthenticationSuccessHandler7004 successHandler;
    @Resource
    private MyAuthenticationFailureHandler7004 failureHandler;
    @Resource
    private MyLogoutSuccessHandler7004 logoutSuccessHandler;
    @Resource
    private MyAuthenticationEntryPoint7004 authenticationEntryPoint;
    @Resource
    private MyAccessDeniedHandler7004 accessDeniedHandler;
    @Resource
    private DataSource dataSource;

    /**
     * 密码加密器
     * @return
     */
    @Bean
    PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }

    /**
     * 根据UserDetailsService定义基于Jdbc的用户
     * 调用 userExists 方法判断用户是否存在,如果不存在,就创建一个新的用户出来(因为每次项目启动时这段代码都会执行,所以加一个判断,避免重复创建用户)
     * @return
     */
    @Bean
    protected UserDetailsService userDetailsService() {
        JdbcUserDetailsManager manager = new JdbcUserDetailsManager();
        manager.setDataSource(dataSource);
        if (!manager.userExists("admin")) {
            manager.createUser(User.withUsername("admin").password("123456").roles("admin").build());
        }
        if (!manager.userExists("dba")) {
            manager.createUser(User.withUsername("dba").password("123456").roles("dba").build());
        }
        return manager;
    }

    /**
     * 角色继承
     * @return
     */
    @Bean
    protected RoleHierarchy roleHierarchy() {
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
        roleHierarchy.setHierarchy("ROLE_admin > ROLE_dba");

        return roleHierarchy;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/dba/**").hasRole("dba")
                .antMatchers("/admin/**").hasRole("admin")
                .antMatchers("/helloWorld")
                .permitAll()
                .anyRequest()
                .authenticated()

                .and()

                /**
                 * 登录成功 & 登录失败回调
                 */
                .formLogin()
                .loginPage("/login")
                .successHandler(successHandler)
                .failureHandler(failureHandler)

                .and()

                /**
                 * 注销登录回调
                 */
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessHandler(logoutSuccessHandler)
                .permitAll()

                .and()

                .csrf()
                .disable()

                /**
                 * 未认证 & 权限不足回调
                 */
                .exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint)
                .accessDeniedHandler(accessDeniedHandler);
    }

}

1.5、启动服务会往表中插入数据,如下

系列七、Spring Security中基于Jdbc的用户认证 & 授权_第3张图片

1.6、测试

        测试流程同【系列六、Spring Security中的认证 & 授权 & 角色继承​​​​​​​】,这里不再赘述。

你可能感兴趣的:(Spring,Security,OAuth2.0系列,Spring,Security,OAuth2.0)