Spring Boot聚合项目:达内知道(二)-Mybatis Plus、Spring Security

1.Mybatis Plus

1.1 什么是Mybatis Plus?

  Mybatis Plus是一个对Mybatis框架进行了增强的框架,在保留原有功能的基础上,又增加了一些实用的功能(mybatis封装了底层的JDBC代码,用于对数据库进行操作,详见:Mybatis框架 - 梦想家小崔 - 博客园 https://www.cnblogs.com/XiaoCui-blog/p/15110488.html)。

  左侧的代表mybatis plus(有个小星星,表示增强),右侧的代表mybatis,mybatis plus是mybatis的增强版。

1.2 添加依赖

  我们现在portal项目的依赖都没有添加版本,因为我们继承的Spring Boot 2.3.12.RELEASE这个项目中已经定义了开发中常用的框架的版本。但是Mybatis Plus这个框架的版本没有在Spring Boot 2.3.12中定义,所以我们添加依赖要加版本。但是多个模块都添加依赖版本会造成版本号维护问题,所以企业中的做法是在父项目中定义一次版本,子项目中来使用,当需要维护版本时,只需要修改父项目中的版本即可。

先在父项目knows中的pom.xml文件中添加mybatis plus版本和依赖:

     <properties>
         <!--java版本-->
         <java.version>1.8</java.version>
         <!--mybatis-plus版本-->
         <mybatis.plus.version>3.3.1</mybatis.plus.version>
     </properties>
  <!--添加依赖管理,管理版本-->
     <dependencyManagement>
         <dependencies>
             <!--${mybatis.plus.version}:取mybatis.plus.version里面的内容-->
             <dependency>
                 <groupId>com.baomidou</groupId>
                 <artifactId>mybatis-plus-extension</artifactId>
                 <version>${mybatis.plus.version}</version>
             </dependency>
             <dependency>
                 <groupId>com.baomidou</groupId>
                 <artifactId>mybatis-plus-boot-starter</artifactId>
                 <version>${mybatis.plus.version}</version>
             </dependency>
             <dependency>
                 <groupId>com.baomidou</groupId>
                 <artifactId>mybatis-plus-generator</artifactId>
                 <version>${mybatis.plus.version}</version>
             </dependency>
         </dependencies>
     </dependencyManagement>

子项目knows-portal的pom.xml文件的最终依赖:

     <!--添加依赖-->
     <dependencies>
         <!--spring-boot-starter-web-->
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
         </dependency>
 
         <!--测试依赖-->
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>
             <scope>test</scope>
             <exclusions>
                 <exclusion>
                     <groupId>org.junit.vintage</groupId>
                     <artifactId>junit-vintage-engine</artifactId>
                 </exclusion>
             </exclusions>
         </dependency>
 
         <!--添加lombok工具依赖,简化get、set、toString方法等书写-->
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
         </dependency>
 
         <!--mybatis-plus框架,版本已在父版本中定义-->
         <dependency>
             <groupId>com.baomidou</groupId>
             <artifactId>mybatis-plus-boot-starter</artifactId>
         </dependency>
 
         <!-- 连接MySQL数据库的依赖,版本在SpringBoot已定义 -->
         <dependency>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>
         </dependency>
     </dependencies>

1.3 Mybatis Plus功能一:自动生成方法

  Mybatis Plus 框架主要新增了两个实用的功能,第一是可以通过实现一个接口自动实现基本增删改查方法。

为了测试,我们新建一个对应Tag表的实体类

 @Data
 public class Tag {
     private Integer id;
     private String name;
     private String createby;
     private String createtime;
 
 }

创建mapper包,包中新建TagMapper:

 // 我们连接操作数据库的Mapper接口要继承一个父接口BaseMapper
 // BaseMapper这个接口中已经编写好了基本的增删改查方法,无需我们编写
 // <Tag>:表示当前在这个Mapper对哪个表生成代码
 @Repository //@Component注解会将对象存储到Spring容器中,但@Repository不仅可以进行存储对象,还可以进行数据库操作
 public interface TagMapper extends BaseMapper<Tag> {
 }

在SpringBoot启动类中,添加扫描包的代码:

 package cn.tedu.knows.portal;
 
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 
 @SpringBootApplication
 //mybatis-plus框架指定扫描的包,定位到mapper
 //效果是将指定的包中的所有类都具备相当于添加了@Mapper注解的效果
 @MapperScan("cn.tedu.knows.portal.mapper")
 public class KnowsPortalApplication {
 
     public static void main(String[] args) {
         SpringApplication.run(KnowsPortalApplication.class, args);
    }
 
 }
 

注意:如果启动类没有添加@MapperScan(“cn.tedu.know.portal.mapper”),报如下异常:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'cn.tedu.know.portal.KnowPortalApplicationTests': Unsatisfied dependency expressed through field 'mapper'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'cn.tedu.know.portal.mapper.TagMapper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

在application.properties文件中进行数据库配置:

 # 连接数据库,注意数据库名为knows、MariaDB端口号为3307
 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
 spring.datasource.url=jdbc:mysql://localhost:3307/knows?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
 spring.datasource.username=root
 spring.datasource.password=root

在测试类中测试功能:

 @Autowired //自动装配(相当于从Spring容器中取出来用)
 TagMapper tagMapper;
 //新增一个Tag
 @Test
 public void testTag(){
     Tag tag=new Tag();
     tag.setId(21);
     tag.setName("微服务");
     tag.setCreateby("tom");
     tag.setCreatetime("2021-08-23 11:23:00");//注意时间格式严格书写
     //使用BaseMapper提供的方法执行新增操作
     tagMapper.insert(tag);
     System.out.println("ok");
 }
 
 //按id查询Tag
 @Test
 public void testId(){
     Tag tag=tagMapper.selectById(21);
     System.out.println(tag);
 }
 
 // 全查所有Tag
 @Test
 public void testAll(){
     List<Tag> tags=tagMapper.selectList(null);//null处添加条件,为null表示查询所有
     for(Tag tag: tags){
         System.out.println(tag);
    }
 }
 
 //修改一个标签对象
 @Test
 public void testUpdate(){
     //修改一个对象要先查出来
     Tag tag=tagMapper.selectById(21);
     //将想修改的属性进行修改(不能改id)
     tag.setCreateby("admin");
     //执行修改
     tagMapper.updateById(tag);
     System.out.println("ok");
 }
 
 //按id删除
 @Test
 public void testDelete(){
     //删除我们测试时新增的标签
     tagMapper.deleteById(21);
     System.out.println("ok");
 }

注意:如果使用mapper时没有先添加@Autowired,报如下异常:

java.lang.NullPointerException

at cn.tedu.know.portal.KnowPortalApplicationTests.testId(KnowPortalApplicationTests.java:38)

1.4 显示Sql语句在控制台

  上面经过测试,我们验证了Mybatis Plus框架是可以自动生成基本操作语句的,但是运行了什么样的语句,我们不知道。如果想观察sql语句的运行,我们需要配置日志级别。

首先了解日志级别分级:

  • trace 痕迹 低重要级别

  • debug 打桩输出(调试)

  • info 信息

  • warn 警告

  • error 错误 高重要级别

  SpringBoot框架默认显示的是Info以上级别的信息,Mybatis框架把sql语句的运行信息放在了debug级别,所以我们只需要将SpringBoot输出日志的级别修改为debug,就可以看到Mybatis运行的sql语句了。

需要在application.properties文件中添加日志配置:

 # 设置cn.tedu.konws.portal包中的所有类的日志输出级别:
 # debug级别及以上级别信息会输出到控制台显示,也叫设置门槛
 logging.level.cn.tedu.knows.portal = debug

测试代码:

 @SpringBootTest
 @Slf4j //注意:使用log.debug或info等要先引入@Slf4j
 class KnowPortalApplicationTests {
     @Autowired
     TagMapper mapper;
 
  //按id查询tag
     @Test
     public void testId(){
         Tag tag = mapper.selectById(1);
         System.out.println(tag);
         //log.debug("debug");//此处写不写在控制台都会输出对应sql语句的日志信息,因为已在配置文件中设置日志门槛
         //log.info("info");
    }
 }

显示结果:

1.5 Mybatis Plus功能二:代码生成器

  在实际开发中,数据库中每个表都要有对应的实体类 \ 控制器 \ 数据访问层 \ 业务逻辑层的代码,项目越大,表越多,这个步骤就越繁琐。为了减轻这个负担,Mybatis Plus提供了代码生成器,能够根据数据库中的表自动生成这一系列的数据。

创建项目

  因为代码生成是需要一些指令和配置的,但是这些指令和配置是只运行一次的,所以最好单独放在一个项目中。

创建父项目knows的子项目knows-generator:

父项目的pom.xml添加子项目:

 <modules>
     <module>knows-portal</module>
     <module>knows-generator</module>
 </modules>

子项目的knows-generator的pom.xml:进行父子相认、添加依赖

 <?xml version="1.0" encoding="UTF-8"?>
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <!--父子相认-->
         <groupId>cn.tedu</groupId>
         <artifactId>knows</artifactId>
         <version>0.0.1-SNAPSHOT</version>
         <relativePath/> <!-- lookup parent from repository -->
     </parent>
     <groupId>cn.tedu</groupId>
     <artifactId>knows-generator</artifactId>
     <version>0.0.1-SNAPSHOT</version>
     <name>knows-generator</name>
     <description>Demo project for Spring Boot</description>
     <!--添加依赖-->
     <dependencies>
         <!--springboot启动类-->
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter</artifactId>
         </dependency>
         
         <!--springboot代码生成器-->
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-freemarker</artifactId>
         </dependency>
         
         <!--mybatis-plus启动类-->
         <dependency>
             <groupId>com.baomidou</groupId>
             <artifactId>mybatis-plus-boot-starter</artifactId>
         </dependency>
 
         <!--mybatis代码生成器-->
         <dependency>
             <groupId>com.baomidou</groupId>
             <artifactId>mybatis-plus-generator</artifactId>
         </dependency>
         <dependency>
             <groupId>com.baomidou</groupId>
             <artifactId>mybatis-plus-extension</artifactId>
         </dependency>
 
         <!--数据库连接-->
         <dependency>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>
         </dependency>
 
         <!--lombok简化方法-->
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
         </dependency>
     </dependencies>
 </project>

在cn.tedu.knows.generator下创建包code,包中创建类CodeGenerator,复制苍老师网站的CodeGenerator类中的代码(代码生成器现成代码),修改类的属性位置:

 //数据库连接参数
 public static String driver = "com.mysql.cj.jdbc.Driver";
 //                                             ↓↓↓端口号、数据库名↓↓↓
 public static String url = "jdbc:mysql://localhost:3306/knows?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true";
 public static String username="root";
 //                       ↓↓↓数据库密码↓↓↓
 public static String password="root";
 //父级别包名称                               ↓↓↓数据库名↓↓↓
 public static String parentPackage = "cn.tedu.knows";
 //代码生成的目标路径               ↓↓↓数据库名↓↓↓
 public static String generateTo = "/knows-generator/src/main/java";
 //mapper.xml的生成路径               ↓↓↓数据库名↓↓↓
 public static String mapperXmlPath = "/knows-generator/src/main/resources/mapper";
 //控制器的公共基类,用于抽象控制器的公共方法,null值表示没有父类
 public static String baseControllerClassName ;// = "cn.tedu.straw.portal.base.BaseController";
 //业务层的公共基类,用于抽象公共方法
 public static String baseServiceClassName ;   // = "cn.tedu.straw.portal.base.BaseServiceImpl";
 //作者名
 public static String author = "tedu.cn";
 //模块名称,用于组成包名
 public static String modelName = "portal";
 //Mapper接口的模板文件,不用写后缀 .ftl
 public static String mapperTempalte = "/ftl/mapper.java";

删除knows-generator项目的src下的test文件夹,否则报错(一定要先删除test文件夹,在进行下面操作,否则在portal进行测试时会出现各种各样的错误)。

在src/main/resources文件夹下创建ftl文件夹,在ftl文件夹中创建文件mapper.java.ftl(前面即文件全称),代码从苍老师网站复制。

 import ${package.Entity}.${entity};
 import ${superMapperClassPackage};
 import org.springframework.stereotype.Repository;
 
 /**
 * <p>
    * ${table.comment!} Mapper 接口
    * </p>
 *
 * @author ${author}
 * @since ${date}
 */
 <#if kotlin>
    interface ${table.mapperName} : ${superMapperClass}<${entity}>
 <#else>
    @Repository
    public interface ${table.mapperName} extends ${superMapperClass}<${entity}> {
 
    }
 </#if>
 Spring-Security starter
 <!-- Spring Security -->
 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
 </dependency>
 <!-- Spring Security Test -->
 <dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <scope>test</scope>
 </dependency>

然后运行CodeGenerator中的main 方法,运行后输入表名:all,其中,"all"表示所有,然后回车:

运行完成后观察控制台输出:

得到上面结果,表示一切正常。将knows-generator项目的cn.tedu.knows.portal包中生成的四个包:mapper、controller、model 、service复制到knows-portal项目中:

然后删除knows-generator项目的cn.tedu.knows.portal包:

最后测试生成的代码是否可用:

(1)测试mapper是否可用:

在knows-portal项目的test文件夹下新建一个测试类TestMapper,代码如下:

 package cn.tedu.knows.portal;
 
 import cn.tedu.knows.portal.mapper.TagMapper;
 import cn.tedu.knows.portal.model.Tag;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 
 //新建的测试类必须加这个@SpringBootTest注解,不加这个注解运行就是空指针异常
 @SpringBootTest
 public class TestMapper {
     @Autowired
     TagMapper tagMapper;
     @Test
     public void mapper(){
         Tag tag = tagMapper.selectById(1);
         System.out.println(tag);
    }
 }
 

输出结果:

前面进行日志配置后,可以显示sql语句:

查询结果:

(2)测试controller是否可用:

在controller包中修改UserController,代码如下:

 package cn.tedu.knows.portal.controller;
 
 
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 import org.springframework.web.bind.annotation.RestController;
 
 /**
  * <p>
  * 前端控制器
  * </p>
  *
  * @author tedu.cn
  * @since 2021-08-23
  */
 @RestController
 //为今后微服务项目方便起见,根据微服务标准,
 //将@RequestMapping("/portal/user")改为@RequestMapping("/v1/users")
 @RequestMapping("/v1/users")
 public class UserController {
     // 类上编写RequestMapping,表示这个类中的所有控制器方法路径都以/v1/users开头
     // 企业中开发要求确定请求是get还是post,不推荐直接使用RequestMapping
     // get请求用@GetMapping
     // post请求用@PostMapping
     //下面的这个方法请求的全路径为:"http://localhost:8080/v1/users/get"
     @GetMapping("/get")
     public String get(){
         System.out.println("运行了get方法");
         return "运行了get方法";
    }
 }
 

启动项目KnowsPortalApplication,浏览器输入地址,http://localhost:8080/v1/users/get,得到输出结果!

(1)浏览器(注意自己的端口为8888)

(2)控制台

 

2.Spring 安全框架

2.1 Spring 安全框架概述

  我们要先完成达内知道项目的登录功能,我们自己编写登录的安全性是非常不可靠的。菜鸟程序员要想写出企业级的安全登录,就需要依靠框架来实现。

  Spring-Security是Spring提供的安全管理框架,是Spring生态系统提供的关于安全方面的框架,它能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案。这个框架中包含了登录部分的核心代码,非常安全,我们只需要按照框架要求的数据编写传入即可。Spring-Security框架不止完成登录功能,还能帮我们实现项目中的权限管理等功能。

2.2 初步使用Spring-Security

  要想使用Spring-Security,需要添加依赖,在knows-portal项目的pom.xml添加如下依赖:

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

  Spring-Security的使用相当便捷,只要添加依赖,当前项目的所有资源就被它保护起来了。重启portal服务,访问任何路径,都需要先登录才能访问:

  用户名是user,密码在启动服务的控制台中以随机UUID给出,只有输入此UUID密码才能正确登录。

  如果想自定义用户名密码,需要在application.properties进行配置:

 # 设置Spring-Security框架的用户名和密码
 spring.security.user.name=admin
 spring.security.user.password=123456

  重启服务,使用我们自定义的用户名密码来登录。同时你会发现,控制台就没有再出现那个随机的密码了。

2.3 密码加密

  如果按照上面的配置,任何人看到这个配置文件都可以登录这个系统,安全性没有保证。我们要做到,即使有人看到了我们的密码,它也无法登录,这个功能实现就需要密码加密。我们使用bcrypt加密规则,将我们的密码加密之后保存,保证安全。

  我们创建一个测试类TestPwd来学习密码加密的过程:

 package cn.tedu.knows.portal;
 
 import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.security.crypto.password.PasswordEncoder;
 
 //测试类添加@SpringBootTest注解
 @SpringBootTest
 public class TestPwd {
     //利用bcrypt加密算法进行密码编码       提示键:BPE
     PasswordEncoder encoder = new BCryptPasswordEncoder();
     //加密方法
     @Test
     public void encoder(){
         //与application.properties里面配置的密码一致
         String str = "123456";
         //对上面的密码进行加密
         String pwd = encoder.encode(str);
         //输出加密后的密码
         System.out.println(pwd);
         //输出结果:每次生成结果不一样,这是加密算法故意的,这种现象叫“随机加盐”技术
         //$2a$10$KJepr.ccS6tVn8wBabdww.AS4LRKMOlk7Dqgo6DxZjq80EUWGl2q6
         //$2a$10$6Jksgy0cmEqWrNjNSlbuFOjcSwwIk7CabzfNBgv3KUM1E86.eWiH2
         //$2a$10$9H/IgyoaDC6O02aE4oShvOFgZ1i6lREVENhEj5KRVM4VdDNkrh/Uu
    }
 
     //验证字符串是否匹配加密结果
     @Test
     public void matchTest(){
         //测试我们的密码123456是否匹配上面方法生成的加密字符串
         //matches([明文字符串],[加密结果])返回是否匹配
         boolean b = encoder.matches("123456","$2a$10$9H/IgyoaDC6O02aE4oShvOFgZ1i6lREVENhEj5KRVM4VdDNkrh/Uu");
         System.out.println(b);//输出true,与上面的密码不一样时返回false
    }
 }
 

  把加密结果(加密后的加密字符串)应用到配置文件中,使用密文密码替换原始密码进行保存,其中,password属性后面多了{bcrypt},表示该密码是用bcrypt加密算法加密后的字符串。

 # 设置Spring-Security框架的用户名和密码
 spring.security.user.name=admin
 spring.security.user.password={bcrypt}$2a$10$oHmgE95Z0pzIo0hKPF8L/ufqvD1D51y9waiLjx6xDX60cktZ7pFL.

  再次启动服务,用设定前的用户名和密码(admin、123456)进行登录即可。

2.3 使用java代码配置权限管理

  登录这个网站的用户肯定是数据库中的用户,那么必须在java代码中进行登录而不是在配置文件中。我们先体会一下怎么在java代码中设置用户名和密码,以体验登录效果。

在cn.tedu.knows.portal下面新建包security,包中新建类SecurityConfig,代码如下:

 package cn.tedu.knows.portal.security;
 
 import org.springframework.context.annotation.Configuration;
 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
 import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 
 @Configuration
 //提示键:EGMS 启动SpringBoot的权限管理功能,设置prePostEnabled = true,此处必须要设置
 @EnableGlobalMethodSecurity(prePostEnabled = true)
 public class SecurityConfig extends WebSecurityConfigurerAdapter {
     //编写一个方法,java代码中设置用户名密码实现登录
 
     @Override
     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
         auth.inMemoryAuthentication()
                .withUser("tom")
                .password("{bcrypt}$2a$10$9H/IgyoaDC6O02aE4oShvOFgZ1i6lREVENhEj5KRVM4VdDNkrh/Uu")
                .authorities("get");//只有拥有了此访问资格才能访问,否则不能访问。一般页面登录后就可以访问。
         //此处设置了新的用户名tom和刚才密码生成的密码串,此级别高于application.properties里面设置的用户名和密码,使用此用户名和密码才能登录成功
    }
 }
 

重启服务,用tom登录测试

(1)用户名:admin、密码:123456登录,提示登录失败

(2)用户名:tom、密码:123456,登陆成功

 

  上面的.authorities中可以指定当前用户都拥有什么资格,里面的内容可以是一个字符串,也可以是一个字符串数组,内容不固定。.authorities("get")设置了当前用户的资格,不一定是get,也可以是 abc 等一些随机的内容。修改SecurityConfig:

 package cn.tedu.know.portal.security;
 
 import org.springframework.context.annotation.Configuration;
 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
 import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 
 @Configuration
 //提示键:EGMS 启动SpringBoot的权限管理功能,设置prePostEnabled = true,此处必须要设置
 @EnableGlobalMethodSecurity(prePostEnabled = true)
 //继承WebSecurityConfigurerAdapter
 public class SecurityConfig extends WebSecurityConfigurerAdapter {
     //编写一个方法,java代码中设置用户名密码实现登录
     //重写configure(AuthenticationManagerBuilder auth)方法
     @Override
     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
         auth.inMemoryAuthentication()
                .withUser("tom") //设置用户名
                .password("{bcrypt}$2a$10$9H/IgyoaDC6O02aE4oShvOFgZ1i6lREVENhEj5KRVM4VdDNkrh/Uu")//设置密码
                .authorities("bbb");//此处里面的内容是资格,具有该资格才能访问
         //此处设置了新的用户名tom和刚才密码生成的密码串,此级别高于application.properties里面设置的用户名和密码,使用此用户名和密码才能登录成功。
    }
 }

  达内知道项目需要设置这样的资格,约束哪些用户有哪些功能,我们需要在控制器方法中进行设置,例如下面代码:UserController.java 。

 package cn.tedu.know.portal.controller;
 
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 import org.springframework.web.bind.annotation.RestController;
 
 /**
  * <p>
  * 前端控制器
  * </p>
  *
  * @author tedu.cn
  * @since 2021-08-28
  */
 @RestController
 //为今后微服务项目方便起见,根据微服务标准,
 //将@RequestMapping("/portal/user")改为@RequestMapping("/v1/users")
 @RequestMapping("/v1/users")
 public class UserController {
     // 类上编写RequestMapping,表示这个类中的所有控制器方法路径都以/v1/users开头
     // 企业中开发要求确定请求是get还是post,不推荐直接使用RequestMapping
     // get请求用@GetMapping
     // post请求用@PostMapping
     //下面的这个方法请求的全路径为:"http://localhost:8080/v1/users/get"
     @GetMapping("/get")
     //设置要访问这个方法需要aaa资格
     @PreAuthorize("hasAuthority('aaa')")
     public String get(){
         System.out.println("拥有aaa资格访问的get");
         return "拥有bbb资格访问的get";
    }
 
     /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/
     //测试用户拥有指定资格才可以访问的方法
     //如果没有指定特殊资格,默认登录成功就可以访问
     //下面的这个方法请求的全路径为:"http://localhost:8080/v1/users/info"
     @GetMapping("/info")
     //设置要访问这个方法需要bbb资格,和.authorities("bbb")对应
     @PreAuthorize("hasAuthority('bbb')")
     public String info(){
         System.out.println("拥有bbb资格访问的info");
         return "拥有bbb资格访问的info";
    }
 }

重启启动服务

  • 如果当前用户拥有bbb资格,登录后正常访问/v1/users/info;

  • 如果当前用户不拥有aaa资格,登录后访问/v1/users/get提示403错误

    • 403错误就是表示当前用户权限不足或者没有权限,不能访问的意思,和404不一样

 

posted @ 2021-08-23 21:43  Coder_Cui  阅读(457)  评论(0编辑  收藏  举报