• Spring Security 基础教程 -- 基于数据库的认证


    准备工作

    这里涉及数据库的操作,所以首先需要在数据库中导入相应的表格,这里用的 SQL 文件来自江南一点雨

    pom.xml 所需依赖:

           <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.3</version>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
                <version>8.0.16</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>1.1.23</version>
            </dependency>
    

    这里使用 mybatis 操作数据库,关于 mybatis 的基本使用,参考文章:在 Spring Boot 中使用 Mybtais

    application.properties 配置文件如下:

    spring.datasource.url=jdbc:mysql://localhost:3306/security?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
    spring.datasource.username=root
    spring.datasource.password=123456
    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
    

    示例

    bean

    新建两个实体类:Users 和 Role

    Users 类继承接口 UserDetails ,具体如下:

    @Data
    public class Users implements UserDetails {
        private Integer id;
        private String username;
        private String password;
        private Boolean enabled;
        private Boolean locked;
        // 一个用户可能有多个角色
        private List<Role> roles;
    
        /**
         * 返回用户的所有角色
         * @return
         */
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            List<SimpleGrantedAuthority> authorities = new ArrayList<>();
            for (Role role:roles){
                authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName()));
            }
            return authorities;
        }
    
        /**
         * 账户是否未过期
         * @return
         */
        @Override
        public boolean isAccountNonExpired() {
            return true;
        }
    
        /**
         * 账户是否未锁定
         * @return
         */
        @Override
        public boolean isAccountNonLocked() {
            return !locked;
        }
    
        /**
         * 密码是否未过期
         * @return
         */
        @Override
        public boolean isCredentialsNonExpired() {
            return true;
        }
    
        /**
         * 是否可用
         * @return
         */
        @Override
        public boolean isEnabled() {
            return enabled;
        }
    }
    

    Role 类如下:

    @Data
    public class Role {
        private Integer id;
        private String name;
        private String nameZh;
    }
    

    mapper

    新建接口 UserMapper:

    @Mapper
    public interface UserMapper {
        Users loadUserByUsername(String username);
    
        List<Role> getUserRoleById(Integer id);
    
    }
    

    这里定义了两个方法,通过用户名查询用户,和通过用户id查询用户。

    新建和 UserMapper 映射的 xml 文件,实现上面两个方法:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://www.mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.example.securitydb.mapper.UserMapper">
        <select id="loadUserByUsername" resultType="com.example.securitydb.bean.Users">
            select * from user where username=#{username}
        </select>
    
        <select id="getUserRoleById" resultType="com.example.securitydb.bean.Role">
            select * from role where id in (select rid from user_role where uid=#{id})
        </select>
    </mapper>
    

    为了使 UserMapper 生效,需要在 pom.xml 文件中配置一下:

            <resources>
                <resource>
                    <directory>src/main/java</directory>
                    <includes>
                        <include>**/*.xml</include>
                    </includes>
                </resource>
                <resource>
                    <directory>src/main/resources</directory>
                </resource>
            </resources>
    

    service

    新建 UserService 类,继承接口 UserDetailsService,调用 UserMapper 中的两个方法:

    @Service
    public class UserService implements UserDetailsService {
    
        @Autowired
        UserMapper userMapper;
    
        /**
         * 根据用户名查询用户对象返回
         * 参数为用户名
         */
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            Users user = userMapper.loadUserByUsername(username);
            if (user == null) {
                throw new UsernameNotFoundException("用户名不存在!");
            }
            user.setRoles(userMapper.getUserRoleById(user.getId()));
            return user;
        }
    }
    

    config

    新建 SecurityConfig 类,继承 WebSecurityConfigurerAdapter。将 UserService 注入进来,并对不同角色进行权限控制:

    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        UserService userService;
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userService);
        }
    
        @Bean
        PasswordEncoder passwordEncoder(){
            return new BCryptPasswordEncoder();
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    // 设置不同角色的访问权限
                    .antMatchers("/dba/**").hasRole("dba")
                    .antMatchers("/admin/**").hasRole("admin")
                    .antMatchers("/user/**").hasRole("user")
                    // 其他访问路径,只要登录后就可以
                    .anyRequest().authenticated()
                    .and()
                    // 登录表单设置
                    .formLogin()
                    .permitAll()
                    .and()
                    .csrf().disable();
        }
    }
    

    关于 SecurityConfig 的配置,参考文章:Spring Security 基础教程 -- HttpSecurity 权限和登录表单配置

    controller

    写一个 HelloController 类,测试上述权限控制是否生效:

    @RestController
    public class HelloController {
        @GetMapping("/hello")
        public String hello(){
            return "hello Security!";
        }
    
        @GetMapping("/dba/hello")
        public String dba(){
            return "hello dba!";
        }
    
        @GetMapping("/admin/hello")
        public String root(){
            return "hello admin!";
        }
    
        @GetMapping("/user/hello")
        public String user(){
            return "hello user!";
        }
    }
    

    此时,完整目录如下:

    测试

    启动项目,访问 http://localhost:8080/hello,只需要登录任一账号,就能成功访问。

    访问 http://localhost:8080/dba/hello,需要角色 dba

    访问 http://localhost:8080/admin/hello,需要角色 admin.

    每天学习一点点,每天进步一点点。

  • 相关阅读:
    pgspider sqlite mysql docker 镜像
    pgspider docker 镜像
    pgspider基于pg 的高性能数据可视化sql 集群引擎
    diesel rust orm 框架试用
    golang 条件编译
    Performance Profiling Zeebe
    bazel 学习一 简单java 项目运行
    一个好用node http keeplive agnet
    gox 简单灵活的golang 跨平台编译工具
    mailhog 作为smtp server mock工具
  • 原文地址:https://www.cnblogs.com/youcoding/p/13922905.html
Copyright © 2020-2023  润新知