SpringBoot整合Spring Security,使用数据库鉴权(四)

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 需要注意的是,配置文件如果是yml文件类型的,密码一定要加单引号或者双引号,不然连接不了数据库的,properties不存在这个问题。

一、实现UserDetails接口

package com.example.securityzimug.config.auth;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
public class MyUserDetails implements UserDetails {
    String password; //密码
    String username;  //用户名
    boolean accountNonExpired;   //是否没过期
    boolean accountNonLocked;   //是否没被锁定
    boolean credentialsNonExpired;  //是否没过期
    boolean enabled;  //账号是否可用
    Collection<? extends GrantedAuthority> authorities;  //用户的权限集合
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }
    @Override
    public String getPassword() {
        return password;
    }
    @Override
    public String getUsername() {
        return username;
    }
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    @Override
    public boolean isEnabled() {
        return enabled;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public void setAccountNonExpired(boolean accountNonExpired) {
        this.accountNonExpired = accountNonExpired;
    }
    public void setAccountNonLocked(boolean accountNonLocked) {
        this.accountNonLocked = accountNonLocked;
    }
    public void setCredentialsNonExpired(boolean credentialsNonExpired) {
        this.credentialsNonExpired = credentialsNonExpired;
    }
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }
    public void setAuthorities(Collection<? extends GrantedAuthority> authorities) {
        this.authorities = authorities;
    }
}


二、编写mapper

在编写之前需要导入依赖。

        <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>
        </dependency>


package com.example.securityzimug.config.auth;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface MyUserDetailsServiceMapper {
    //根据userID查询用户信息
    @Select("SELECT username,password,enabled\n" +
            "FROM sys_user u\n" +
            "WHERE u.username = #{userId} or u.phone = #{userId}")
    MyUserDetails findByUserName(@Param("userId") String userId);
    //根据userID查询用户角色列表
    @Select("SELECT role_code\n" +
            "FROM sys_role r\n" +
            "LEFT JOIN sys_user_role ur ON r.id = ur.role_id\n" +
            "LEFT JOIN sys_user u ON u.id = ur.user_id\n" +
            "WHERE u.username = #{userId} or u.phone = #{userId}")
    List<String> findRoleByUserName(@Param("userId") String userId);
    //根据用户角色查询用户权限
    @Select({
      "<script>",
         "SELECT url " ,
         "FROM sys_menu m " ,
         "LEFT JOIN sys_role_menu rm ON m.id = rm.menu_id " ,
         "LEFT JOIN sys_role r ON r.id = rm.role_id ",
         "WHERE r.role_code IN ",
         "<foreach collection='roleCodes' item='roleCode' open='(' separator=',' close=')'>",
            "#{roleCode}",
         "</foreach>",
      "</script>"
    })
    List<String> findAuthorityByRoleCodes(@Param("roleCodes") List<String> roleCodes);
}


三、实现UserDetailsService接口

package com.example.securityzimug.config.auth;
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.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
/**
 * @author baikunlong
 * @date 2020/9/22 23:14
 */
@Component
public class MyUserDetailsService implements UserDetailsService {
    @Resource
    private MyUserDetailsServiceMapper myUserDetailsServiceMapper;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        MyUserDetails myUserDetails = myUserDetailsServiceMapper.findByUserName(username);
        //角色集合
        List<String> roleList = myUserDetailsServiceMapper.findRoleByUserName(username);
        //资源权限集合
        List<String> authorities = myUserDetailsServiceMapper.findAuthorityByRoleCodes(roleList);
        //角色是特殊的权限,前缀规定为ROLE_
        roleList=roleList.stream().map(role->"ROLE_"+role).collect(Collectors.toList());
        authorities.addAll(roleList);
        myUserDetails.setAuthorities(AuthorityUtils.commaSeparatedStringToAuthorityList(String.join(",",authorities)));
        return myUserDetails;
    }
}


四、修改配置类

2020092309043078.png


注意这里的UserDetailsService一定要使用注入方式,我一开始手动new的,这会导致mapper为空,在service那排错了很久,后来才发现是这边的问题。

20200923090551627.png


五、修改配置文件

spring:
  security:
#    用数据库后,内存模式的就先注释掉吧
#    user:
#      name: admin
#      password: admin
    loginType: JSON
  datasource:
    url: jdbc:mysql://localhost:3306/study_springboot_05_security_zimug?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: '123456'
    driver-class-name: com.mysql.cj.jdbc.Driver
#logging:
#  level:
#    root: debug


需要注意的是,配置文件如果是yml文件类型的,密码一定要加单引号或者双引号,不然连接不了数据库的,properties不存在这个问题。


六、动态鉴权

在一开始我们的鉴权都是写的静态的,当有新需求时可能会更改代码,所以需要动态的鉴权。


编写一个类来鉴权。

package com.example.securityzimug.config.auth;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@Component("rabcService")
public class MyRBACService {
    /**
     * 判断某用户是否具有该request资源的访问权限
     */
    public boolean hasPermission(HttpServletRequest request, Authentication authentication){
        //这个就是UserDetails
        Object principal = authentication.getPrincipal();
        if(principal instanceof UserDetails){
            UserDetails userDetails = ((UserDetails)principal);
            //这里的请求地址就是资源权限名
            List<GrantedAuthority> authorityList =
                    AuthorityUtils.commaSeparatedStringToAuthorityList(request.getRequestURI());
            //判断当前用户是否有这个资源权限
            return userDetails.getAuthorities().contains(authorityList.get(0));
        }
        return false;
    }
}


然后在配置类里更改下权限配置:

20200923100745395.png

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
27天前
|
存储 安全 Java
Spring Boot整合Spring Security--学习笔记
Spring Boot整合Spring Security--学习笔记
45 0
|
6天前
|
安全 数据安全/隐私保护
Springboot+Spring security +jwt认证+动态授权
Springboot+Spring security +jwt认证+动态授权
|
26天前
|
消息中间件 JSON Java
Spring Boot、Spring Cloud与Spring Cloud Alibaba版本对应关系
Spring Boot、Spring Cloud与Spring Cloud Alibaba版本对应关系
319 0
|
5天前
|
安全 Java 数据库
Spring Security加密解密
Spring Security加密解密
|
6天前
|
Java 测试技术 数据库
SpringBoot启动时设置不加载数据库
SpringBoot启动时设置不加载数据库
|
6天前
|
Java 容器
SpringBoot使用配置注解开启自动配置功能&整合spring-boot-configuration-processor
SpringBoot使用配置注解开启自动配置功能&整合spring-boot-configuration-processor
11 0
|
24天前
|
SQL Java 数据库连接
springboot解析txt文件顺便加到数据库中(nohup文件)
springboot解析txt文件顺便加到数据库中(nohup文件)
108 1
|
25天前
|
安全 Java 数据库
Spring Security 权限管理详解与案例
Spring Security 是 Spring 框架中用于提供认证和访问控制的模块。它保护了成千上万的应用程序,使其免受未经授权的访问。本文将详细介绍 Spring Security 的权限管理功能,并通过一个实际案例来展示其用法。
45 0
|
26天前
|
缓存 NoSQL Java
spring cache整合redis实现springboot项目中的缓存功能
spring cache整合redis实现springboot项目中的缓存功能
42 1
|
5天前
|
Java Linux
Springboot 解决linux服务器下获取不到项目Resources下资源
Springboot 解决linux服务器下获取不到项目Resources下资源