目录
3.子项目新建Controllter层,并建立BlogLoginController.java
4.在servic 层定义login 方法,并new UsernamePasswordAuthenticationToken对象,传入对应用户名,密码
7.我们还希望在认证失败或者是授权失败的情况下也能和我们的接口一样返回相同结构的json,这样可以让前端能对响应进行统一的处理。要实现这个功能我们需要知道SpringSecurity的异常处理机制。
9.授权流程,在SpringSecurity中,会使用默认的FilterSecurityInterceptor来进行权限校验。
1. 设置父工程 添加依赖
  
   - 
    
     
    
    
     
      <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     
    
 
   - 
    
     
    
    
         
      <modelVersion>4.0.0
      </modelVersion>
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      <groupId>com.wang
      </groupId>
     
    
 
   - 
    
     
    
    
         
      <artifactId>WangBlog
      </artifactId>
     
    
 
   - 
    
     
    
    
         
      <packaging>pom
      </packaging>
     
    
 
   - 
    
     
    
    
         
      <version>1.0-SNAPSHOT
      </version>
     
    
 
   - 
    
     
    
    
         
      <modules>
     
    
 
   - 
    
     
    
    
             
      <module>wang-framework
      </module>
     
    
 
   - 
    
     
    
    
             
      <module>wang-admin
      </module>
     
    
 
   - 
    
     
    
    
             
      <module>wang-blog
      </module>
     
    
 
   - 
    
     
    
    
         
      </modules>
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      <properties>
     
    
 
   - 
    
     
    
    
             
      <maven.compiler.source>8
      </maven.compiler.source>
     
    
 
   - 
    
     
    
    
             
      <maven.compiler.target>8
      </maven.compiler.target>
     
    
 
   - 
    
     
    
    
             
      <project.build.sourceEncoding>UTF-8
      </project.build.sourceEncoding>
     
    
 
   - 
    
     
    
    
         
      </properties>
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      <dependencyManagement>
     
    
 
   - 
    
     
    
    
             
      <dependencies>
     
    
 
   - 
    
     
    
    
                 
      <!-- SpringBoot的依赖配置-->
     
    
 
   - 
    
     
    
    
                 
      <dependency>
     
    
 
   - 
    
     
    
    
                     
      <groupId>org.springframework.boot
      </groupId>
     
    
 
   - 
    
     
    
    
                     
      <artifactId>spring-boot-dependencies
      </artifactId>
     
    
 
   - 
    
     
    
    
                     
      <version>2.5.0
      </version>
     
    
 
   - 
    
     
    
    
                     
      <type>pom
      </type>
     
    
 
   - 
    
     
    
    
                     
      <scope>import
      </scope>
     
    
 
   - 
    
     
    
    
                 
      </dependency>
     
    
 
   - 
    
     
    
    
                 
      <!--fastjson依赖-->
     
    
 
   - 
    
     
    
    
                 
      <dependency>
     
    
 
   - 
    
     
    
    
                     
      <groupId>com.alibaba
      </groupId>
     
    
 
   - 
    
     
    
    
                     
      <artifactId>fastjson
      </artifactId>
     
    
 
   - 
    
     
    
    
                     
      <version>1.2.33
      </version>
     
    
 
   - 
    
     
    
    
                 
      </dependency>
     
    
 
   - 
    
     
    
    
                 
      <!--jwt依赖-->
     
    
 
   - 
    
     
    
    
                 
      <dependency>
     
    
 
   - 
    
     
    
    
                     
      <groupId>io.jsonwebtoken
      </groupId>
     
    
 
   - 
    
     
    
    
                     
      <artifactId>jjwt
      </artifactId>
     
    
 
   - 
    
     
    
    
                     
      <version>0.9.0
      </version>
     
    
 
   - 
    
     
    
    
                 
      </dependency>
     
    
 
   - 
    
     
    
    
                 
      <!--mybatisPlus依赖-->
     
    
 
   - 
    
     
    
    
                 
      <dependency>
     
    
 
   - 
    
     
    
    
                     
      <groupId>com.baomidou
      </groupId>
     
    
 
   - 
    
     
    
    
                     
      <artifactId>mybatis-plus-boot-starter
      </artifactId>
     
    
 
   - 
    
     
    
    
                     
      <version>3.4.3
      </version>
     
    
 
   - 
    
     
    
    
                 
      </dependency>
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
                 
      <!--阿里云OSS-->
     
    
 
   - 
    
     
    
    
                 
      <dependency>
     
    
 
   - 
    
     
    
    
                     
      <groupId>com.aliyun.oss
      </groupId>
     
    
 
   - 
    
     
    
    
                     
      <artifactId>aliyun-sdk-oss
      </artifactId>
     
    
 
   - 
    
     
    
    
                     
      <version>3.10.2
      </version>
     
    
 
   - 
    
     
    
    
                 
      </dependency>
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
                 
      <dependency>
     
    
 
   - 
    
     
    
    
                     
      <groupId>com.alibaba
      </groupId>
     
    
 
   - 
    
     
    
    
                     
      <artifactId>easyexcel
      </artifactId>
     
    
 
   - 
    
     
    
    
                     
      <version>3.0.5
      </version>
     
    
 
   - 
    
     
    
    
                 
      </dependency>
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
                 
      <dependency>
     
    
 
   - 
    
     
    
    
                     
      <groupId>io.springfox
      </groupId>
     
    
 
   - 
    
     
    
    
                     
      <artifactId>springfox-swagger2
      </artifactId>
     
    
 
   - 
    
     
    
    
                     
      <version>2.9.2
      </version>
     
    
 
   - 
    
     
    
    
                 
      </dependency>
     
    
 
   - 
    
     
    
    
                 
      <dependency>
     
    
 
   - 
    
     
    
    
                     
      <groupId>io.springfox
      </groupId>
     
    
 
   - 
    
     
    
    
                     
      <artifactId>springfox-swagger-ui
      </artifactId>
     
    
 
   - 
    
     
    
    
                     
      <version>2.9.2
      </version>
     
    
 
   - 
    
     
    
    
                 
      </dependency>
     
    
 
   - 
    
     
    
    
             
      </dependencies>
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      </dependencyManagement>
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      <build>
     
    
 
   - 
    
     
    
    
             
      <plugins>
     
    
 
   - 
    
     
    
    
                 
      <plugin>
     
    
 
   - 
    
     
    
    
                     
      <groupId>org.apache.maven.plugins
      </groupId>
     
    
 
   - 
    
     
    
    
                     
      <artifactId>maven-compiler-plugin
      </artifactId>
     
    
 
   - 
    
     
    
    
                     
      <version>3.1
      </version>
     
    
 
   - 
    
     
    
    
                     
      <configuration>
     
    
 
   - 
    
     
    
    
                         
      <source>${java.version}
      </source>
     
    
 
   - 
    
     
    
    
                         
      <target>${java.version}
      </target>
     
    
 
   - 
    
     
    
    
                         
      <encoding>${project.build.sourceEncoding}
      </encoding>
     
    
 
   - 
    
     
    
    
                     
      </configuration>
     
    
 
   - 
    
     
    
    
                 
      </plugin>
     
    
 
   - 
    
     
    
    
             
      </plugins>
     
    
 
   - 
    
     
    
    
         
      </build>
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      </project>
     
    
 
  
  
2.在子工程通过easyCode创建项目相关包和文件


如图然后点击确定即可。
子工程pom文件:
  
   - 
    
     
    
    
     
      <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     
    
 
   - 
    
     
    
    
         
      <parent>
     
    
 
   - 
    
     
    
    
             
      <artifactId>WangBlog
      </artifactId>
     
    
 
   - 
    
     
    
    
             
      <groupId>com.wang
      </groupId>
     
    
 
   - 
    
     
    
    
             
      <version>1.0-SNAPSHOT
      </version>
     
    
 
   - 
    
     
    
    
         
      </parent>
     
    
 
   - 
    
     
    
    
         
      <modelVersion>4.0.0
      </modelVersion>
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      <artifactId>wang-blog
      </artifactId>
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      <properties>
     
    
 
   - 
    
     
    
    
             
      <maven.compiler.source>8
      </maven.compiler.source>
     
    
 
   - 
    
     
    
    
             
      <maven.compiler.target>8
      </maven.compiler.target>
     
    
 
   - 
    
     
    
    
             
      <project.build.sourceEncoding>UTF-8
      </project.build.sourceEncoding>
     
    
 
   - 
    
     
    
    
         
      </properties>
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      <dependencies>
     
    
 
   - 
    
     
    
    
             
      <dependency>
     
    
 
   - 
    
     
    
    
                 
      <groupId>com.wang
      </groupId>
     
    
 
   - 
    
     
    
    
                 
      <artifactId>wang-framework
      </artifactId>
     
    
 
   - 
    
     
    
    
                 
      <version>1.0-SNAPSHOT
      </version>
     
    
 
   - 
    
     
    
    
             
      </dependency>
     
    
 
   - 
    
     
    
    
             
      <dependency>
     
    
 
   - 
    
     
    
    
                 
      <groupId>org.springframework.boot
      </groupId>
     
    
 
   - 
    
     
    
    
                 
      <artifactId>spring-boot-autoconfigure
      </artifactId>
     
    
 
   - 
    
     
    
    
                 
      <version>2.3.7.RELEASE
      </version>
     
    
 
   - 
    
     
    
    
                 
      <scope>compile
      </scope>
     
    
 
   - 
    
     
    
    
             
      </dependency>
     
    
 
   - 
    
     
    
    
         
      </dependencies>
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      </project>
     
    
 
  
  
 
3.子项目新建Controllter层,并建立BlogLoginController.java
  
   - 
    
     
    
    
     
      package com.wang.controller;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import com.wang.entity.ResponseResult;
     
    
 
   - 
    
     
    
    
     
      import com.wang.entity.User;
     
    
 
   - 
    
     
    
    
     
      import com.wang.enums.AppHttpCodeEnum;
     
    
 
   - 
    
     
    
    
     
      import com.wang.exception.SystemException;
     
    
 
   - 
    
     
    
    
     
      import com.wang.service.BlogLoginService;
     
    
 
   - 
    
     
    
    
     
      import io.swagger.annotations.Api;
     
    
 
   - 
    
     
    
    
     
      import io.swagger.annotations.ApiOperation;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.beans.factory.annotation.Autowired;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.util.StringUtils;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.web.bind.annotation.PostMapping;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.web.bind.annotation.RequestBody;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.web.bind.annotation.RestController;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      /**
     
    
 
   - 
    
     
    
    
     
       * @author 飞
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
     
      @RestController
     
    
 
   - 
    
     
    
    
     
      @Api(tags = "登录",description = "博客登录相关接口")
     
    
 
   - 
    
     
    
    
     
      public 
      class 
      BlogLoginController {
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      @Autowired
     
    
 
   - 
    
     
    
    
         
      private BlogLoginService blogLoginService;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * @param user
     
    
 
   - 
    
     
    
    
     
       * @return ResponseResult
     
    
 
   - 
    
     
    
    
     
       * 登陆
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      @PostMapping("/login")
     
    
 
   - 
    
     
    
    
         
      @ApiOperation(value = "登陆",notes = "登陆")
     
    
 
   - 
    
     
    
    
         
      public ResponseResult 
      login
      (@RequestBody User user){
     
    
 
   - 
    
     
    
    
             
      if (!StringUtils.hasText(user.getUserName())||!StringUtils.hasText(user.getPassword())){
     
    
 
   - 
    
     
    
    
                 
      throw 
      new 
      SystemException(AppHttpCodeEnum.LOGIN_ERROR);
     
    
 
   - 
    
     
    
    
     
              }
     
    
 
   - 
    
     
    
    
             
      return blogLoginService.login(user);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      @PostMapping("/logout")
     
    
 
   - 
    
     
    
    
         
      @ApiOperation(value = "退出登陆",notes = "退出登陆")
     
    
 
   - 
    
     
    
    
         
      public ResponseResult 
      logout
      (){
     
    
 
   - 
    
     
    
    
             
      return blogLoginService.logout();
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
     
      }
     
    
 
  
  
4.在servic 层定义login 方法,并new UsernamePasswordAuthenticationToken对象,传入对应用户名,密码
  
   - 
    
     
    
    
         
      @Override
     
    
 
   - 
    
     
    
    
         
      public ResponseResult 
      login
      (User user) {
     
    
 
   - 
    
     
    
    
             
      UsernamePasswordAuthenticationToken 
      authenticationToken 
      = 
      new 
      UsernamePasswordAuthenticationToken(user.getUserName(),user.getPassword());
     
    
 
   - 
    
     
    
    
             
      Authentication 
      authenticate 
      = authenticationManager.authenticate(authenticationToken);
     
    
 
   - 
    
     
    
    
             
      //判断是否认证通过
     
    
 
   - 
    
     
    
    
             
      if(Objects.isNull(authenticate)){
     
    
 
   - 
    
     
    
    
                 
      throw 
      new 
      RuntimeException(
      "用户名或密码错误");
     
    
 
   - 
    
     
    
    
     
              }
     
    
 
   - 
    
     
    
    
             
      //获取userid 生成token
     
    
 
   - 
    
     
    
    
             
      LoginUser 
      loginUser 
      = (LoginUser) authenticate.getPrincipal();
     
    
 
   - 
    
     
    
    
             
      String 
      userId 
      = loginUser.getUser().getId().toString();
     
    
 
   - 
    
     
    
    
             
      String 
      jwt 
      = JwtUtil.createJWT(userId);
     
    
 
   - 
    
     
    
    
             
      //把用户信息存入redis
     
    
 
   - 
    
     
    
    
     
              redisCache.setCacheObject(
      "bloglogin:"+userId,loginUser);
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
             
      //把token和userinfo封装 返回
     
    
 
   - 
    
     
    
    
             
      //把User转换成UserInfoVo
     
    
 
   - 
    
     
    
    
             
      UserInfoVo 
      userInfoVo 
      = BeanCopyUtils.copyBean(loginUser.getUser(), UserInfoVo.class);
     
    
 
   - 
    
     
    
    
             
      BlogUserLoginVo 
      vo 
      = 
      new 
      BlogUserLoginVo(jwt,userInfoVo);
     
    
 
   - 
    
     
    
    
             
      return ResponseResult.okResult(vo);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
  
  
5.自定义实现类,实现UserDetailsService接口,重写loadUserByUsername方法,并查询数据库用户的权限信息封装传入到UserDetails。第4步中UsernamePasswordAuthenticationToken先执行到本步骤。
  
   - 
    
     
    
    
     
      @Service
     
    
 
   - 
    
     
    
    
     
      public 
      class 
      UserDetailServiceImpl 
      implements 
      UserDetailsService {
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      @Autowired
     
    
 
   - 
    
     
    
    
         
      private UserMapper userMapper;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      @Autowired
     
    
 
   - 
    
     
    
    
         
      private MenuMapper menuMapper;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      @Override
     
    
 
   - 
    
     
    
    
         
      public UserDetails 
      loadUserByUsername
      (String username) 
      throws UsernameNotFoundException {
     
    
 
   - 
    
     
    
    
             
      //根据用户名查询信息
     
    
 
   - 
    
     
    
    
     
              LambdaQueryWrapper<User> lambdaQueryWrapper = 
      new 
      LambdaQueryWrapper<>();
     
    
 
   - 
    
     
    
    
     
              lambdaQueryWrapper.eq(User::getUserName, username);
     
    
 
   - 
    
     
    
    
             
      User 
      user 
      = userMapper.selectOne(lambdaQueryWrapper);
     
    
 
   - 
    
     
    
    
             
      if (user == 
      null) {
     
    
 
   - 
    
     
    
    
                 
      throw 
      new 
      RuntimeException(
      "用户不存在");
     
    
 
   - 
    
     
    
    
     
              }
     
    
 
   - 
    
     
    
    
             
      //返回用户信息
     
    
 
   - 
    
     
    
    
             
      //TODO 如果是后天需要权限封装
     
    
 
   - 
    
     
    
    
             
      if (
      "1".equals(user.getType())){
     
    
 
   - 
    
     
    
    
     
                  List<String> list = menuMapper.selectPermsByUserId(user.getId());
     
    
 
   - 
    
     
    
    
                 
      return 
      new 
      LoginUser(user, list);
     
    
 
   - 
    
     
    
    
     
              }
     
    
 
   - 
    
     
    
    
             
      return 
      new 
      LoginUser(user,
      null);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
  
  
loadUserByUsername返回类型为UserDetails,我们通过定义一个类实现UserDetails接口,重新其中的方法。
  
   - 
    
     
    
    
     
      @Data
     
    
 
   - 
    
     
    
    
     
      @AllArgsConstructor
     
    
 
   - 
    
     
    
    
     
      @NoArgsConstructor
     
    
 
   - 
    
     
    
    
     
      public 
      class 
      LoginUser 
      implements 
      UserDetails {
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      private User user;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      private List<String> permissions;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      @Override
     
    
 
   - 
    
     
    
    
         
      public Collection<? 
      extends 
      GrantedAuthority> getAuthorities() {
     
    
 
   - 
    
     
    
    
             
      return 
      null;
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      @Override
     
    
 
   - 
    
     
    
    
         
      public String 
      getPassword
      () {
     
    
 
   - 
    
     
    
    
             
      return user.getPassword();
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      @Override
     
    
 
   - 
    
     
    
    
         
      public String 
      getUsername
      () {
     
    
 
   - 
    
     
    
    
             
      return user.getUserName();
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      @Override
     
    
 
   - 
    
     
    
    
         
      public 
      boolean 
      isAccountNonExpired
      () {
     
    
 
   - 
    
     
    
    
             
      return 
      true;
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      @Override
     
    
 
   - 
    
     
    
    
         
      public 
      boolean 
      isAccountNonLocked
      () {
     
    
 
   - 
    
     
    
    
             
      return 
      true;
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      @Override
     
    
 
   - 
    
     
    
    
         
      public 
      boolean 
      isCredentialsNonExpired
      () {
     
    
 
   - 
    
     
    
    
             
      return 
      true;
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      @Override
     
    
 
   - 
    
     
    
    
         
      public 
      boolean 
      isEnabled
      () {
     
    
 
   - 
    
     
    
    
             
      return 
      true;
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
     
      }
     
    
 
  
  
6.自定义一个JwtAuthenticationTokenFilter过滤器,这个过滤器会去获取每次请求当中的token,对token进行解析取出其中的userid。使用userid去redis中获取对应的LoginUser对象。然后封装Authentication对象存入SecurityContextHolder
  
   - 
    
     
    
    
     
      package com.wang.filter;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import com.alibaba.fastjson.JSON;
     
    
 
   - 
    
     
    
    
     
      import com.wang.entity.LoginUser;
     
    
 
   - 
    
     
    
    
     
      import com.wang.entity.ResponseResult;
     
    
 
   - 
    
     
    
    
     
      import com.wang.enums.AppHttpCodeEnum;
     
    
 
   - 
    
     
    
    
     
      import com.wang.utils.JwtUtil;
     
    
 
   - 
    
     
    
    
     
      import com.wang.utils.RedisCache;
     
    
 
   - 
    
     
    
    
     
      import com.wang.utils.WebUtils;
     
    
 
   - 
    
     
    
    
     
      import io.jsonwebtoken.Claims;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.beans.factory.annotation.Autowired;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.core.context.SecurityContextHolder;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.stereotype.Component;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.util.StringUtils;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.web.filter.OncePerRequestFilter;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import javax.servlet.FilterChain;
     
    
 
   - 
    
     
    
    
     
      import javax.servlet.ServletException;
     
    
 
   - 
    
     
    
    
     
      import javax.servlet.http.HttpServletRequest;
     
    
 
   - 
    
     
    
    
     
      import javax.servlet.http.HttpServletResponse;
     
    
 
   - 
    
     
    
    
     
      import java.io.IOException;
     
    
 
   - 
    
     
    
    
     
      import java.util.Objects;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      /**
     
    
 
   - 
    
     
    
    
     
       * @description: 自定义一个JwtAuthenticationTokenFilter过滤器,这个过滤器会去获取每次请求当中的token,对token进行解析取出其中的userid。
     
    
 
   - 
    
     
    
    
     
       * 使用userid去redis中获取对应的LoginUser对象。
     
    
 
   - 
    
     
    
    
     
       * 然后封装Authentication对象存入SecurityContextHolder
     
    
 
   - 
    
     
    
    
     
       * @author: wang fei
     
    
 
   - 
    
     
    
    
     
       * @date: 2023/1/13 19:52:24
     
    
 
   - 
    
     
    
    
     
      **/
     
    
 
   - 
    
     
    
    
     
      @Component
     
    
 
   - 
    
     
    
    
     
      public 
      class 
      JwtAuthenticationTokenFilter  
      extends 
      OncePerRequestFilter {
     
    
 
   - 
    
     
    
    
         
      @Autowired
     
    
 
   - 
    
     
    
    
         
      private RedisCache redisCache;
     
    
 
   - 
    
     
    
    
         
      @Override
     
    
 
   - 
    
     
    
    
         
      protected 
      void 
      doFilterInternal
      (HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) 
      throws ServletException, IOException {
     
    
 
   - 
    
     
    
    
             
      //获取请求头中的token
     
    
 
   - 
    
     
    
    
             
      String 
      token 
      = httpServletRequest.getHeader(
      "token");
     
    
 
   - 
    
     
    
    
             
      if (!StringUtils.hasText(token)) {
     
    
 
   - 
    
     
    
    
                 
      //说明该接口不需要登录 直接放行
     
    
 
   - 
    
     
    
    
     
                  filterChain.doFilter(httpServletRequest, httpServletResponse);
     
    
 
   - 
    
     
    
    
                 
      return;
     
    
 
   - 
    
     
    
    
     
              }
     
    
 
   - 
    
     
    
    
             
      //解析userId
     
    
 
   - 
    
     
    
    
             
      Claims 
      claims 
      = 
      null;
     
    
 
   - 
    
     
    
    
             
      try {
     
    
 
   - 
    
     
    
    
     
                  claims = JwtUtil.parseJWT(token);
     
    
 
   - 
    
     
    
    
     
              } 
      catch (Exception e) {
     
    
 
   - 
    
     
    
    
     
                  e.printStackTrace();
     
    
 
   - 
    
     
    
    
                 
      //token超时或token非法
     
    
 
   - 
    
     
    
    
                 
      //给前端提示需要登陆
     
    
 
   - 
    
     
    
    
                 
      ResponseResult 
      result 
      = ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
     
    
 
   - 
    
     
    
    
     
                  WebUtils.renderString(httpServletResponse, JSON.toJSONString(result));
     
    
 
   - 
    
     
    
    
                 
      return;
     
    
 
   - 
    
     
    
    
     
              }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
             
      String 
      userId 
      = claims.getSubject();
     
    
 
   - 
    
     
    
    
             
      //从redis中获取用户信息
     
    
 
   - 
    
     
    
    
             
      LoginUser 
      longinUser 
      = redisCache.getCacheObject(
      "bloglogin:" + userId);
     
    
 
   - 
    
     
    
    
             
      //如果获取不到
     
    
 
   - 
    
     
    
    
             
      if (Objects.isNull(longinUser)) {
     
    
 
   - 
    
     
    
    
                 
      //说明登陆过期 提示重新登陆
     
    
 
   - 
    
     
    
    
                 
      ResponseResult 
      result 
      = ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
     
    
 
   - 
    
     
    
    
     
                  WebUtils.renderString(httpServletResponse, JSON.toJSONString(result));
     
    
 
   - 
    
     
    
    
                 
      return;
     
    
 
   - 
    
     
    
    
     
              }
     
    
 
   - 
    
     
    
    
             
      //存入SecurityContextHolder
     
    
 
   - 
    
     
    
    
             
      UsernamePasswordAuthenticationToken 
      usernamePasswordAuthenticationToken 
      = 
      new 
      UsernamePasswordAuthenticationToken(longinUser, 
      null, 
      null);
     
    
 
   - 
    
     
    
    
     
              SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
             
      //放行
     
    
 
   - 
    
     
    
    
     
              filterChain.doFilter(httpServletRequest, httpServletResponse);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
  
  
7.我们还希望在认证失败或者是授权失败的情况下也能和我们的接口一样返回相同结构的json,这样可以让前端能对响应进行统一的处理。要实现这个功能我们需要知道SpringSecurity的异常处理机制。
在SpringSecurity中,如果我们在认证或者授权的过程中出现了异常会被ExceptionTranslationFilter捕获到。在ExceptionTranslationFilter中会去判断是认证失败还是授权失败出现的异常。
如果是认证过程中出现的异常会被封装成AuthenticationException然后调用AuthenticationEntryPoint对象的方法去进行异常处理。
 如果是授权过程中出现的异常会被封装成AccessDeniedException然后调用AccessDeniedHandler对象的方法去进行异常处理。
 所以如果我们需要自定义异常处理,我们只需要自定义AuthenticationEntryPoint和AccessDeniedHandler然后配置给SpringSecurity即可。
自定义实现类:
AccessDeniedHandlerImpl.java
  
   - 
    
     
    
    
     
      package com.wang.handler.security;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import com.alibaba.fastjson.JSON;
     
    
 
   - 
    
     
    
    
     
      import com.wang.entity.ResponseResult;
     
    
 
   - 
    
     
    
    
     
      import com.wang.enums.AppHttpCodeEnum;
     
    
 
   - 
    
     
    
    
     
      import com.wang.utils.WebUtils;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.access.AccessDeniedException;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.web.access.AccessDeniedHandler;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.stereotype.Component;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import javax.servlet.ServletException;
     
    
 
   - 
    
     
    
    
     
      import javax.servlet.http.HttpServletRequest;
     
    
 
   - 
    
     
    
    
     
      import javax.servlet.http.HttpServletResponse;
     
    
 
   - 
    
     
    
    
     
      import java.io.IOException;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      /**
     
    
 
   - 
    
     
    
    
     
       * @author 飞
     
    
 
   - 
    
     
    
    
     
       * 如果是授权过程中出现的异常会被封装成AccessDeniedException然后调用AccessDeniedHandler对象的方法去进行异常处理。
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
     
      @Component
     
    
 
   - 
    
     
    
    
     
      public 
      class 
      AccessDeniedHandlerImpl 
      implements 
      AccessDeniedHandler {
     
    
 
   - 
    
     
    
    
         
      @Override
     
    
 
   - 
    
     
    
    
         
      public 
      void 
      handle
      (HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) 
      throws IOException, ServletException {
     
    
 
   - 
    
     
    
    
     
              e.printStackTrace();
     
    
 
   - 
    
     
    
    
             
      ResponseResult 
      result 
      = ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH);
     
    
 
   - 
    
     
    
    
             
      //响应给前端
     
    
 
   - 
    
     
    
    
     
              WebUtils.renderString(httpServletResponse, JSON.toJSONString(result));
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
     
      }
     
    
 
  
  
AuthenticationEntryPointImpl.java
  
   - 
    
     
    
    
     
      package com.wang.handler.security;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import com.alibaba.fastjson.JSON;
     
    
 
   - 
    
     
    
    
     
      import com.wang.entity.ResponseResult;
     
    
 
   - 
    
     
    
    
     
      import com.wang.enums.AppHttpCodeEnum;
     
    
 
   - 
    
     
    
    
     
      import com.wang.utils.WebUtils;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.authentication.BadCredentialsException;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.authentication.InsufficientAuthenticationException;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.core.AuthenticationException;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.web.AuthenticationEntryPoint;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.stereotype.Component;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import javax.servlet.ServletException;
     
    
 
   - 
    
     
    
    
     
      import javax.servlet.http.HttpServletRequest;
     
    
 
   - 
    
     
    
    
     
      import javax.servlet.http.HttpServletResponse;
     
    
 
   - 
    
     
    
    
     
      import java.io.IOException;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      /**
     
    
 
   - 
    
     
    
    
     
       * @author 飞
     
    
 
   - 
    
     
    
    
     
       * 如果是认证过程中出现的异常会被封装成AuthenticationException然后调用AuthenticationEntryPoint对象的方法去进行异常处理。
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
     
      @Component
     
    
 
   - 
    
     
    
    
     
      public 
      class 
      AuthenticationEntryPointImpl 
      implements 
      AuthenticationEntryPoint {
     
    
 
   - 
    
     
    
    
         
      @Override
     
    
 
   - 
    
     
    
    
         
      public 
      void 
      commence
      (HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) 
      throws IOException, ServletException {
     
    
 
   - 
    
     
    
    
     
              e.printStackTrace();
     
    
 
   - 
    
     
    
    
     
              ResponseResult result=
      null;
     
    
 
   - 
    
     
    
    
             
      if (e 
      instanceof BadCredentialsException){
     
    
 
   - 
    
     
    
    
     
                  result=ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_ERROR.getCode(), e.getMessage());
     
    
 
   - 
    
     
    
    
     
              } 
      else 
      if (e 
      instanceof InsufficientAuthenticationException) {
     
    
 
   - 
    
     
    
    
     
                  result=ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_ERROR);
     
    
 
   - 
    
     
    
    
     
              }
      else {
     
    
 
   - 
    
     
    
    
     
                  result = ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR.getCode(),
      "认证或授权失败");
     
    
 
   - 
    
     
    
    
     
              }
     
    
 
   - 
    
     
    
    
             
      //响应给前端
     
    
 
   - 
    
     
    
    
     
              WebUtils.renderString(httpServletResponse, JSON.toJSONString(result));
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
     
      }
     
    
 
  
  
8.自定义配置类
  
   - 
    
     
    
    
     
      package com.wang.config;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import com.wang.filter.JwtAuthenticationTokenFilter;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.beans.factory.annotation.Autowired;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.context.annotation.Bean;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.context.annotation.Configuration;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.authentication.AuthenticationManager;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.config.annotation.web.builders.HttpSecurity;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.config.http.SessionCreationPolicy;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.crypto.password.PasswordEncoder;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.web.AuthenticationEntryPoint;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.web.access.AccessDeniedHandler;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      /**
     
    
 
   - 
    
     
    
    
     
       * @author 飞
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
     
      @Configuration
     
    
 
   - 
    
     
    
    
     
      public 
      class 
      SecurityConfig 
      extends 
      WebSecurityConfigurerAdapter {
     
    
 
   - 
    
     
    
    
         
      @Autowired
     
    
 
   - 
    
     
    
    
         
      private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
     
    
 
   - 
    
     
    
    
         
      @Autowired
     
    
 
   - 
    
     
    
    
     
          AuthenticationEntryPoint authenticationEntryPoint;
     
    
 
   - 
    
     
    
    
         
      @Autowired
     
    
 
   - 
    
     
    
    
     
          AccessDeniedHandler accessDeniedHandler;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      @Bean
     
    
 
   - 
    
     
    
    
         
      public PasswordEncoder 
      passwordEncoder
      (){
     
    
 
   - 
    
     
    
    
             
      return 
      new 
      BCryptPasswordEncoder();
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
         
      @Override
     
    
 
   - 
    
     
    
    
         
      protected 
      void 
      configure
      (HttpSecurity http) 
      throws Exception {
     
    
 
   - 
    
     
    
    
     
              http
     
    
 
   - 
    
     
    
    
                     
      //关闭csrf
     
    
 
   - 
    
     
    
    
     
                      .csrf().disable()
     
    
 
   - 
    
     
    
    
                     
      //不通过Session获取SecurityContext
     
    
 
   - 
    
     
    
    
     
                      .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
     
    
 
   - 
    
     
    
    
     
                      .and()
     
    
 
   - 
    
     
    
    
     
                      .authorizeRequests()
     
    
 
   - 
    
     
    
    
                     
      // 对于登录接口 允许匿名访问
     
    
 
   - 
    
     
    
    
     
                      .antMatchers(
      "/login").anonymous()
     
    
 
   - 
    
     
    
    
                     
      //注销接口需要认证才能访问
     
    
 
   - 
    
     
    
    
     
                      .antMatchers(
      "/logout").authenticated()
     
    
 
   - 
    
     
    
    
     
      // .antMatchers("/upload").authenticated()
     
    
 
   - 
    
     
    
    
                     
      //个人信息接口必须登录后才能访问
     
    
 
   - 
    
     
    
    
     
                      .antMatchers(
      "/user/userInfo").authenticated()
     
    
 
   - 
    
     
    
    
                     
      //jwt过滤器测试用,如果测试没有问题吧这里删除了
     
    
 
   - 
    
     
    
    
     
      // .antMatchers("/link/getAllLink").authenticated()
     
    
 
   - 
    
     
    
    
                     
      // 除上面外的所有请求全部不需要认证即可访问
     
    
 
   - 
    
     
    
    
     
                      .anyRequest().permitAll();
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
             
      //配置异常处理器
     
    
 
   - 
    
     
    
    
     
              http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
     
    
 
   - 
    
     
    
    
     
                      .accessDeniedHandler(accessDeniedHandler);
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
              http.logout().disable();
     
    
 
   - 
    
     
    
    
             
      //关闭默认的注销功能
     
    
 
   - 
    
     
    
    
     
              http.logout().disable();
     
    
 
   - 
    
     
    
    
             
      //把jwtAuthenticationTokenFilter添加到SpringSecurity的过滤器链中
     
    
 
   - 
    
     
    
    
     
              http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
     
    
 
   - 
    
     
    
    
             
      //允许跨域
     
    
 
   - 
    
     
    
    
     
              http.cors();
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
         
      @Override
     
    
 
   - 
    
     
    
    
         
      @Bean
     
    
 
   - 
    
     
    
    
         
      public AuthenticationManager 
      authenticationManagerBean
      () 
      throws Exception {
     
    
 
   - 
    
     
    
    
             
      return 
      super.authenticationManagerBean();
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
     
      }
     
    
 
  
  
9.授权流程,在SpringSecurity中,会使用默认的FilterSecurityInterceptor来进行权限校验。
 
在FilterSecurityInterceptor中会从SecurityContextHolder获取其中的Authentication,然后获取其中的权限信息。当前用户是否拥有访问当前资源所需的权限。
所以我们在项目中只需要把当前登录用户的权限信息也存入Authentication。 

然后设置我们的资源所需要的权限即可。
10.限制访问资源所需权限
SpringSecurity为我们提供了基于注解的权限控制方案,这也是我们项目中主要采用的方式。我们可以使用注解去指定访问对应的资源所需的权限。
 但是要使用它我们需要先开启相关配置springSecurity里面加。
@EnableGlobalMethodSecurity(prePostEnabled = true) 
这里使用定义自己的权限校验方法,在@PreAuthorize注解中使用我们的方法。
例如一个接口需要对应的权限才可以访问,我们这样写:
  
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * @description: 分类导出excel @PreAuthorize("@ps.hasPermission('content:category:export')")判断是否具有content:category:export权限
     
    
 
   - 
    
     
    
    
     
       * @method: exportLink
     
    
 
   - 
    
     
    
    
     
       * @author: wang fei
     
    
 
   - 
    
     
    
    
     
       * @date: 2023/1/13 19:10:13
     
    
 
   - 
    
     
    
    
     
       * @param: [response]
     
    
 
   - 
    
     
    
    
     
       * @return: void
     
    
 
   - 
    
     
    
    
     
       **/
     
    
 
   - 
    
     
    
    
         
      @PreAuthorize("@ps.hasPermission('content:category:export')")
     
    
 
   - 
    
     
    
    
         
      @GetMapping("export")
     
    
 
   - 
    
     
    
    
         
      public 
      void 
      exportLink
      (HttpServletResponse response){
     
    
 
   - 
    
     
    
    
             
      //设置下载文件请求头
     
    
 
   - 
    
     
    
    
             
      try {
     
    
 
   - 
    
     
    
    
     
                  WebUtils.setDownLoadHeader(
      "分类.xlsx",response);
     
    
 
   - 
    
     
    
    
                 
      //提取需要导出的数据
     
    
 
   - 
    
     
    
    
     
                  List<Category> list = categoryService.list();
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
                  List<CategoryVo> categoryVos = BeanCopyUtils.copyBeanList(list, CategoryVo.class);
     
    
 
   - 
    
     
    
    
                 
      //把数据写入到excel中
     
    
 
   - 
    
     
    
    
     
                  EasyExcel.write(response.getOutputStream(), ExcelCategoryVo.class).autoCloseStream(Boolean.FALSE).sheet(
      "分类导出")
     
    
 
   - 
    
     
    
    
     
                          .doWrite(categoryVos);
     
    
 
   - 
    
     
    
    
     
              } 
      catch (Exception e) {
     
    
 
   - 
    
     
    
    
                 
      //如果出现异常也要响应json
     
    
 
   - 
    
     
    
    
                 
      ResponseResult 
      result 
      = ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR);
     
    
 
   - 
    
     
    
    
     
                  WebUtils.renderString(response, JSON.toJSONString(result));
     
    
 
   - 
    
     
    
    
     
              }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
  
  
@PreAuthorize("@ps.hasPermission('content:category:export')"):
ps为我们定义的bean,hasPermission为我们定义的权限判断方法返回类型为bool,content:category:export为权限信息。
  
   - 
    
     
    
    
     
      package com.wang.service.impl;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import com.wang.utils.SecurityUtils;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.stereotype.Service;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import java.util.List;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      /**
     
    
 
   - 
    
     
    
    
     
       * @BelongsProject: WangBlog
     
    
 
   - 
    
     
    
    
     
       * @BelongsPackage: com.wang.service.impl
     
    
 
   - 
    
     
    
    
     
       * @Author: wang fei
     
    
 
   - 
    
     
    
    
     
       * @CreateTime: 2023-01-13 19:04
     
    
 
   - 
    
     
    
    
     
       * @Description: TODO
     
    
 
   - 
    
     
    
    
     
       * @Version: 1.0
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
     
      @Service("ps")
     
    
 
   - 
    
     
    
    
     
      public 
      class 
      PermissionService {
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * @description: 判断当前用户是否具有权限
     
    
 
   - 
    
     
    
    
     
       * @method: hasPermission
     
    
 
   - 
    
     
    
    
     
       * @author: wang fei
     
    
 
   - 
    
     
    
    
     
       * @date: 2023/1/13 19:05:47
     
    
 
   - 
    
     
    
    
     
       * @param: [permission]
     
    
 
   - 
    
     
    
    
     
       * @return: boolean
     
    
 
   - 
    
     
    
    
     
       **/
     
    
 
   - 
    
     
    
    
         
      public  
      boolean 
      hasPermission
      (String permission){
     
    
 
   - 
    
     
    
    
                 
      //如果是超级管理员 直返回true
     
    
 
   - 
    
     
    
    
             
      if (SecurityUtils.isAdmin()) {
     
    
 
   - 
    
     
    
    
                 
      return 
      true;
     
    
 
   - 
    
     
    
    
     
              }
     
    
 
   - 
    
     
    
    
                 
      //否则 获取当前用户的权限列表 判断是否存在权限
     
    
 
   - 
    
     
    
    
     
              List<String> permissions = SecurityUtils.getLoginUser().getPermissions();
     
    
 
   - 
    
     
    
    
             
      return permissions.contains(permission);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
     
      }
     
    
 
  
  
11.其它权限校验方法
 我们前面都是使用@PreAuthorize注解,然后在在其中使用的是hasAuthority方法进行校验。SpringSecurity还为我们提供了其它方法例如:hasAnyAuthority,hasRole,hasAnyRole等。
 这里我们先不急着去介绍这些方法,我们先去理解hasAuthority的原理,然后再去学习其他方法你就更容易理解,而不是死记硬背区别。并且我们也可以选择定义校验方法,实现我们自己的校验逻辑。
 hasAuthority方法实际是执行到了SecurityExpressionRoot的hasAuthority,大家只要断点调试既可知道它内部的校验原理。
 它内部其实是调用authentication的getAuthorities方法获取用户的权限列表。然后判断我们存入的方法参数数据在权限列表中。
 hasAnyAuthority方法可以传入多个权限,只有用户有其中任意一个权限都可以访问对应资源。
  
   - 
    
     
    
    
         
      @PreAuthorize("hasAnyAuthority('admin','test','system:dept:list')")
     
    
 
   - 
    
     
    
    
         
      public String 
      hello
      (){
     
    
 
   - 
    
     
    
    
             
      return 
      "hello";
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
  
 
hasRole要求有对应的角色才可以访问,但是它内部会把我们传入的参数拼接上 ROLE_ 后再去比较。所以这种情况下要用用户对应的权限也要有 ROLE_ 这个前缀才可以。
  
   - 
    
     
    
    
         
      @PreAuthorize("hasRole('system:dept:list')")
     
    
 
   - 
    
     
    
    
         
      public String 
      hello
      (){
     
    
 
   - 
    
     
    
    
             
      return 
      "hello";
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
  
 
hasAnyRole 有任意的角色就可以访问。它内部也会把我们传入的参数拼接上 ROLE_ 后再去比较。所以这种情况下要用用户对应的权限也要有 ROLE_ 这个前缀才可以。
  
   - 
    
     
    
    
         
      @PreAuthorize("hasAnyRole('admin','system:dept:list')")
     
    
 
   - 
    
     
    
    
         
      public String 
      hello
      (){
     
    
 
   - 
    
     
    
    
             
      return 
      "hello";
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
  
 
12.自定义权限校验方法
 我们也可以定义自己的权限校验方法,在@PreAuthorize注解中使用我们的方法。
  
   - 
    
     
    
    
     
      @Component("ex")
     
    
 
   - 
    
     
    
    
     
      public 
      class 
      SGExpressionRoot {
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      public 
      boolean 
      hasAuthority
      (String authority){
     
    
 
   - 
    
     
    
    
             
      //获取当前用户的权限
     
    
 
   - 
    
     
    
    
             
      Authentication 
      authentication 
      = SecurityContextHolder.getContext().getAuthentication();
     
    
 
   - 
    
     
    
    
             
      LoginUser 
      loginUser 
      = (LoginUser) authentication.getPrincipal();
     
    
 
   - 
    
     
    
    
     
              List<String> permissions = loginUser.getPermissions();
     
    
 
   - 
    
     
    
    
             
      //判断用户权限集合中是否存在authority
     
    
 
   - 
    
     
    
    
             
      return permissions.contains(authority);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
     
      }
     
    
 
   - 
    
     
    
    
      
     
    
 
  
 
在SPEL表达式中使用 @ex相当于获取容器中bean的名字未ex的对象。然后再调用这个对象的hasAuthority方法
  
   - 
    
     
    
    
         
      @RequestMapping("/hello")
     
    
 
   - 
    
     
    
    
         
      @PreAuthorize("@ex.hasAuthority('system:dept:list')")
     
    
 
   - 
    
     
    
    
         
      public String 
      hello
      (){
     
    
 
   - 
    
     
    
    
             
      return 
      "hello";
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
  
 
13.基于配置的权限控制
 我们也可以在配置类中使用使用配置的方式对资源进行权限控制。
  
   - 
    
     
    
    
         
      @Override
     
    
 
   - 
    
     
    
    
         
      protected 
      void 
      configure
      (HttpSecurity http) 
      throws Exception {
     
    
 
   - 
    
     
    
    
     
              http
     
    
 
   - 
    
     
    
    
                     
      //关闭csrf
     
    
 
   - 
    
     
    
    
     
                      .csrf().disable()
     
    
 
   - 
    
     
    
    
                     
      //不通过Session获取SecurityContext
     
    
 
   - 
    
     
    
    
     
                      .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
     
    
 
   - 
    
     
    
    
     
                      .and()
     
    
 
   - 
    
     
    
    
     
                      .authorizeRequests()
     
    
 
   - 
    
     
    
    
                     
      // 对于登录接口 允许匿名访问
     
    
 
   - 
    
     
    
    
     
                      .antMatchers(
      "/user/login").anonymous()
     
    
 
   - 
    
     
    
    
     
                      .antMatchers(
      "/testCors").hasAuthority(
      "system:dept:list222")
     
    
 
   - 
    
     
    
    
                     
      // 除上面外的所有请求全部需要鉴权认证
     
    
 
   - 
    
     
    
    
     
                      .anyRequest().authenticated();
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
             
      //添加过滤器
     
    
 
   - 
    
     
    
    
     
              http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
             
      //配置异常处理器
     
    
 
   - 
    
     
    
    
     
              http.exceptionHandling()
     
    
 
   - 
    
     
    
    
                     
      //配置认证失败处理器
     
    
 
   - 
    
     
    
    
     
                      .authenticationEntryPoint(authenticationEntryPoint)
     
    
 
   - 
    
     
    
    
     
                      .accessDeniedHandler(accessDeniedHandler);
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
             
      //允许跨域
     
    
 
   - 
    
     
    
    
     
              http.cors();
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
  
  
14.退出登录
  
   - 
    
     
    
    
     
      public ResponseResult 
      logout
      () {
     
    
 
   - 
    
     
    
    
             
      //获取token 解析获取userid
     
    
 
   - 
    
     
    
    
             
      Authentication 
      authentication 
      = SecurityContextHolder.getContext().getAuthentication();
     
    
 
   - 
    
     
    
    
             
      LoginUser 
      logUser 
      = (LoginUser) authentication.getPrincipal();
     
    
 
   - 
    
     
    
    
             
      //获取userid
     
    
 
   - 
    
     
    
    
             
      Long 
      userId 
      = logUser.getUser().getId();
     
    
 
   - 
    
     
    
    
             
      //删除redis中的用户信息
     
    
 
   - 
    
     
    
    
     
              redisCache.deleteObject(
      "bloglogin:"+userId);
     
    
 
   - 
    
     
    
    
             
      return ResponseResult.okResult();
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
  
 
15.工具类:
BeanCopyUtils.java
  
   - 
    
     
    
    
     
      package com.wang.utils;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import org.springframework.beans.BeanUtils;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import java.util.List;
     
    
 
   - 
    
     
    
    
     
      import java.util.stream.Collectors;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      /**
     
    
 
   - 
    
     
    
    
     
       * @author 飞
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
     
      public 
      class 
      BeanCopyUtils {
     
    
 
   - 
    
     
    
    
         
      private 
      BeanCopyUtils
      () {
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
         
      public 
      static <V> V 
      copyBean
      (Object source, Class<V> clazz){
     
    
 
   - 
    
     
    
    
             
      //创建目标对象
     
    
 
   - 
    
     
    
    
             
      V 
      result 
      = 
      null;
     
    
 
   - 
    
     
    
    
             
      try {
     
    
 
   - 
    
     
    
    
                 
      //反射
     
    
 
   - 
    
     
    
    
     
                  result = clazz.newInstance();
     
    
 
   - 
    
     
    
    
                 
      //实现属性copy
     
    
 
   - 
    
     
    
    
     
                  BeanUtils.copyProperties(source, result);
     
    
 
   - 
    
     
    
    
     
              } 
      catch (InstantiationException | IllegalAccessException e) {
     
    
 
   - 
    
     
    
    
                 
      throw 
      new 
      RuntimeException(e);
     
    
 
   - 
    
     
    
    
     
              }
     
    
 
   - 
    
     
    
    
             
      //返回结果
     
    
 
   - 
    
     
    
    
             
      return result;
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      public 
      static <O,V> List<V> 
      copyBeanList
      (List<O> list, Class<V> clazz){
     
    
 
   - 
    
     
    
    
             
      return list.stream().map(o->copyBean(o, clazz)).collect(Collectors.toList());
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
     
      }
     
    
 
  
  
JwtUtil .java
  
   - 
    
     
    
    
     
      package com.wang.utils;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import io.jsonwebtoken.Claims;
     
    
 
   - 
    
     
    
    
     
      import io.jsonwebtoken.JwtBuilder;
     
    
 
   - 
    
     
    
    
     
      import io.jsonwebtoken.Jwts;
     
    
 
   - 
    
     
    
    
     
      import io.jsonwebtoken.SignatureAlgorithm;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import javax.crypto.SecretKey;
     
    
 
   - 
    
     
    
    
     
      import javax.crypto.spec.SecretKeySpec;
     
    
 
   - 
    
     
    
    
     
      import java.util.Base64;
     
    
 
   - 
    
     
    
    
     
      import java.util.Date;
     
    
 
   - 
    
     
    
    
     
      import java.util.UUID;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      /**
     
    
 
   - 
    
     
    
    
     
       * JWT工具类
     
    
 
   - 
    
     
    
    
     
       * @author 飞
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
     
      public 
      class 
      JwtUtil {
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      //有效期为
     
    
 
   - 
    
     
    
    
         
      public 
      static 
      final 
      Long 
      JWT_TTL 
      = 
      24*
      60 * 
      60 *
      1000L;
      // 60 * 60 *1000 一个小时
     
    
 
   - 
    
     
    
    
         
      //设置秘钥明文
     
    
 
   - 
    
     
    
    
         
      public 
      static 
      final 
      String 
      JWT_KEY 
      = 
      "wangfei";
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      public 
      static String 
      getUUID
      (){
     
    
 
   - 
    
     
    
    
             
      String 
      token 
      = UUID.randomUUID().toString().replaceAll(
      "-", 
      "");
     
    
 
   - 
    
     
    
    
             
      return token;
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
         
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 生成jtw
     
    
 
   - 
    
     
    
    
     
       * @param subject token中要存放的数据(json格式)
     
    
 
   - 
    
     
    
    
     
       * @return
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public 
      static String 
      createJWT
      (String subject) {
     
    
 
   - 
    
     
    
    
             
      JwtBuilder 
      builder 
      = getJwtBuilder(subject, 
      null, getUUID());
      // 设置过期时间
     
    
 
   - 
    
     
    
    
             
      return builder.compact();
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 生成jtw
     
    
 
   - 
    
     
    
    
     
       * @param subject token中要存放的数据(json格式)
     
    
 
   - 
    
     
    
    
     
       * @param ttlMillis token超时时间
     
    
 
   - 
    
     
    
    
     
       * @return
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public 
      static String 
      createJWT
      (String subject, Long ttlMillis) {
     
    
 
   - 
    
     
    
    
             
      JwtBuilder 
      builder 
      = getJwtBuilder(subject, ttlMillis, getUUID());
      // 设置过期时间
     
    
 
   - 
    
     
    
    
             
      return builder.compact();
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      private 
      static JwtBuilder 
      getJwtBuilder
      (String subject, Long ttlMillis, String uuid) {
     
    
 
   - 
    
     
    
    
             
      SignatureAlgorithm 
      signatureAlgorithm 
      = SignatureAlgorithm.HS256;
     
    
 
   - 
    
     
    
    
             
      SecretKey 
      secretKey 
      = generalKey();
     
    
 
   - 
    
     
    
    
             
      long 
      nowMillis 
      = System.currentTimeMillis();
     
    
 
   - 
    
     
    
    
             
      Date 
      now 
      = 
      new 
      Date(nowMillis);
     
    
 
   - 
    
     
    
    
             
      if(ttlMillis==
      null){
     
    
 
   - 
    
     
    
    
     
                  ttlMillis=JwtUtil.JWT_TTL;
     
    
 
   - 
    
     
    
    
     
              }
     
    
 
   - 
    
     
    
    
             
      long 
      expMillis 
      = nowMillis + ttlMillis;
     
    
 
   - 
    
     
    
    
             
      Date 
      expDate 
      = 
      new 
      Date(expMillis);
     
    
 
   - 
    
     
    
    
             
      return Jwts.builder()
     
    
 
   - 
    
     
    
    
     
                      .setId(uuid)              
      //唯一的ID
     
    
 
   - 
    
     
    
    
     
                      .setSubject(subject)   
      // 主题 可以是JSON数据
     
    
 
   - 
    
     
    
    
     
                      .setIssuer(
      "sg")     
      // 签发者
     
    
 
   - 
    
     
    
    
     
                      .setIssuedAt(now)      
      // 签发时间
     
    
 
   - 
    
     
    
    
     
                      .signWith(signatureAlgorithm, secretKey) 
      //使用HS256对称加密算法签名, 第二个参数为秘钥
     
    
 
   - 
    
     
    
    
     
                      .setExpiration(expDate);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 创建token
     
    
 
   - 
    
     
    
    
     
       * @param id
     
    
 
   - 
    
     
    
    
     
       * @param subject
     
    
 
   - 
    
     
    
    
     
       * @param ttlMillis
     
    
 
   - 
    
     
    
    
     
       * @return
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public 
      static String 
      createJWT
      (String id, String subject, Long ttlMillis) {
     
    
 
   - 
    
     
    
    
             
      JwtBuilder 
      builder 
      = getJwtBuilder(subject, ttlMillis, id);
      // 设置过期时间
     
    
 
   - 
    
     
    
    
             
      return builder.compact();
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      public 
      static 
      void 
      main
      (String[] args) 
      throws Exception {
     
    
 
   - 
    
     
    
    
             
      String 
      token 
      = 
      "";
     
    
 
   - 
    
     
    
    
             
      Claims 
      claims 
      = parseJWT(token);
     
    
 
   - 
    
     
    
    
     
              System.out.println(claims);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 生成加密后的秘钥 secretKey
     
    
 
   - 
    
     
    
    
     
       * @return
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public 
      static SecretKey 
      generalKey
      () {
     
    
 
   - 
    
     
    
    
             
      byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
     
    
 
   - 
    
     
    
    
             
      SecretKey 
      key 
      = 
      new 
      SecretKeySpec(encodedKey, 
      0, encodedKey.length, 
      "AES");
     
    
 
   - 
    
     
    
    
             
      return key;
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
         
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 解析
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param jwt
     
    
 
   - 
    
     
    
    
     
       * @return
     
    
 
   - 
    
     
    
    
     
       * @throws Exception
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public 
      static Claims 
      parseJWT
      (String jwt) 
      throws Exception {
     
    
 
   - 
    
     
    
    
             
      SecretKey 
      secretKey 
      = generalKey();
     
    
 
   - 
    
     
    
    
             
      return Jwts.parser()
     
    
 
   - 
    
     
    
    
     
                      .setSigningKey(secretKey)
     
    
 
   - 
    
     
    
    
     
                      .parseClaimsJws(jwt)
     
    
 
   - 
    
     
    
    
     
                      .getBody();
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      }
     
    
 
  
  
PathUtils.java
  
   - 
    
     
    
    
     
      package com.wang.utils;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import java.text.SimpleDateFormat;
     
    
 
   - 
    
     
    
    
     
      import java.util.Date;
     
    
 
   - 
    
     
    
    
     
      import java.util.UUID;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      /**
     
    
 
   - 
    
     
    
    
     
       * @author 飞
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
     
      public 
      class 
      PathUtils {
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      public 
      static String 
      generateFilePath
      (String fileName){
     
    
 
   - 
    
     
    
    
             
      //根据日期生成路径 2022/1/15/
     
    
 
   - 
    
     
    
    
             
      SimpleDateFormat 
      sdf 
      = 
      new 
      SimpleDateFormat(
      "yyyy/MM/dd/");
     
    
 
   - 
    
     
    
    
             
      String 
      datePath 
      = sdf.format(
      new 
      Date());
     
    
 
   - 
    
     
    
    
             
      //uuid作为文件名
     
    
 
   - 
    
     
    
    
             
      String 
      uuid 
      = UUID.randomUUID().toString().replaceAll(
      "-", 
      "");
     
    
 
   - 
    
     
    
    
             
      //后缀和文件后缀一致
     
    
 
   - 
    
     
    
    
             
      int 
      index 
      = fileName.lastIndexOf(
      ".");
     
    
 
   - 
    
     
    
    
             
      // test.jpg -> .jpg
     
    
 
   - 
    
     
    
    
             
      String 
      fileType 
      = fileName.substring(index);
     
    
 
   - 
    
     
    
    
             
      return 
      new 
      StringBuilder().append(datePath).append(uuid).append(fileType).toString();
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
     
      }
     
    
 
  
  
RedisCache.java
  
   - 
    
     
    
    
     
      package com.wang.utils;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import org.springframework.beans.factory.annotation.Autowired;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.data.redis.core.BoundSetOperations;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.data.redis.core.HashOperations;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.data.redis.core.RedisTemplate;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.data.redis.core.ValueOperations;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.stereotype.Component;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import java.util.*;
     
    
 
   - 
    
     
    
    
     
      import java.util.concurrent.TimeUnit;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      /**
     
    
 
   - 
    
     
    
    
     
       * @author 飞
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
     
      @Component
     
    
 
   - 
    
     
    
    
     
      public 
      class 
      RedisCache
     
    
 
   - 
    
     
    
    
     
      {
     
    
 
   - 
    
     
    
    
         
      @Autowired
     
    
 
   - 
    
     
    
    
         
      public RedisTemplate redisTemplate;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 缓存基本的对象,Integer、String、实体类等
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param key 缓存的键值
     
    
 
   - 
    
     
    
    
     
       * @param value 缓存的值
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public <T> 
      void 
      setCacheObject
      (final String key, final T value)
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
     
              redisTemplate.opsForValue().set(key, value);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 缓存基本的对象,Integer、String、实体类等
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param key 缓存的键值
     
    
 
   - 
    
     
    
    
     
       * @param value 缓存的值
     
    
 
   - 
    
     
    
    
     
       * @param timeout 时间
     
    
 
   - 
    
     
    
    
     
       * @param timeUnit 时间颗粒度
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public <T> 
      void 
      setCacheObject
      (final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
     
              redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 设置有效时间
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param key Redis键
     
    
 
   - 
    
     
    
    
     
       * @param timeout 超时时间
     
    
 
   - 
    
     
    
    
     
       * @return true=设置成功;false=设置失败
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public 
      boolean 
      expire
      (final String key, final long timeout)
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
             
      return expire(key, timeout, TimeUnit.SECONDS);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 设置有效时间
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param key Redis键
     
    
 
   - 
    
     
    
    
     
       * @param timeout 超时时间
     
    
 
   - 
    
     
    
    
     
       * @param unit 时间单位
     
    
 
   - 
    
     
    
    
     
       * @return true=设置成功;false=设置失败
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public 
      boolean 
      expire
      (final String key, final long timeout, final TimeUnit unit)
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
             
      return redisTemplate.expire(key, timeout, unit);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 获得缓存的基本对象。
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param key 缓存键值
     
    
 
   - 
    
     
    
    
     
       * @return 缓存键值对应的数据
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public <T> T 
      getCacheObject
      (final String key)
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
     
              ValueOperations<String, T> operation = redisTemplate.opsForValue();
     
    
 
   - 
    
     
    
    
             
      return operation.get(key);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 删除单个对象
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param key
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public 
      boolean 
      deleteObject
      (final String key)
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
             
      return redisTemplate.delete(key);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 删除集合对象
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param collection 多个对象
     
    
 
   - 
    
     
    
    
     
       * @return
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public 
      long 
      deleteObject
      (final Collection collection)
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
             
      return redisTemplate.delete(collection);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 缓存List数据
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param key 缓存的键值
     
    
 
   - 
    
     
    
    
     
       * @param dataList 待缓存的List数据
     
    
 
   - 
    
     
    
    
     
       * @return 缓存的对象
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public <T> 
      long 
      setCacheList
      (final String key, final List<T> dataList)
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
             
      Long 
      count 
      = redisTemplate.opsForList().rightPushAll(key, dataList);
     
    
 
   - 
    
     
    
    
             
      return count == 
      null ? 
      0 : count;
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 获得缓存的list对象
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param key 缓存的键值
     
    
 
   - 
    
     
    
    
     
       * @return 缓存键值对应的数据
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public <T> List<T> 
      getCacheList
      (final String key)
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
             
      return redisTemplate.opsForList().range(key, 
      0, -
      1);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 缓存Set
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param key 缓存键值
     
    
 
   - 
    
     
    
    
     
       * @param dataSet 缓存的数据
     
    
 
   - 
    
     
    
    
     
       * @return 缓存数据的对象
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public <T> BoundSetOperations<String, T> 
      setCacheSet
      (final String key, final Set<T> dataSet)
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
     
              BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
     
    
 
   - 
    
     
    
    
     
              Iterator<T> it = dataSet.iterator();
     
    
 
   - 
    
     
    
    
             
      while (it.hasNext())
     
    
 
   - 
    
     
    
    
     
              {
     
    
 
   - 
    
     
    
    
     
                  setOperation.add(it.next());
     
    
 
   - 
    
     
    
    
     
              }
     
    
 
   - 
    
     
    
    
             
      return setOperation;
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 获得缓存的set
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param key
     
    
 
   - 
    
     
    
    
     
       * @return
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public <T> Set<T> 
      getCacheSet
      (final String key)
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
             
      return redisTemplate.opsForSet().members(key);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 缓存Map
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param key
     
    
 
   - 
    
     
    
    
     
       * @param dataMap
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public <T> 
      void 
      setCacheMap
      (final String key, final Map<String, T> dataMap)
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
             
      if (dataMap != 
      null) {
     
    
 
   - 
    
     
    
    
     
                  redisTemplate.opsForHash().putAll(key, dataMap);
     
    
 
   - 
    
     
    
    
     
              }
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 获得缓存的Map
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param key
     
    
 
   - 
    
     
    
    
     
       * @return
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public <T> Map<String, T> 
      getCacheMap
      (final String key)
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
             
      return redisTemplate.opsForHash().entries(key);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 往Hash中存入数据
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param key Redis键
     
    
 
   - 
    
     
    
    
     
       * @param hKey Hash键
     
    
 
   - 
    
     
    
    
     
       * @param value 值
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public <T> 
      void 
      setCacheMapValue
      (final String key, final String hKey, final T value)
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
     
              redisTemplate.opsForHash().put(key, hKey, value);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 获取Hash中的数据
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param key Redis键
     
    
 
   - 
    
     
    
    
     
       * @param hKey Hash键
     
    
 
   - 
    
     
    
    
     
       * @return Hash中的对象
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public <T> T 
      getCacheMapValue
      (final String key, final String hKey)
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
     
              HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
     
    
 
   - 
    
     
    
    
             
      return opsForHash.get(key, hKey);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 删除Hash中的数据
     
    
 
   - 
    
     
    
    
     
       * 
     
    
 
   - 
    
     
    
    
     
       * @param key
     
    
 
   - 
    
     
    
    
     
       * @param hkey
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public 
      void 
      delCacheMapValue
      (final String key, final String hkey)
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
             
      HashOperations 
      hashOperations 
      = redisTemplate.opsForHash();
     
    
 
   - 
    
     
    
    
     
              hashOperations.delete(key, hkey);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 获取多个Hash中的数据
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param key Redis键
     
    
 
   - 
    
     
    
    
     
       * @param hKeys Hash键集合
     
    
 
   - 
    
     
    
    
     
       * @return Hash对象集合
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public <T> List<T> 
      getMultiCacheMapValue
      (final String key, final Collection<Object> hKeys)
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
             
      return redisTemplate.opsForHash().multiGet(key, hKeys);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 获得缓存的基本对象列表
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param pattern 字符串前缀
     
    
 
   - 
    
     
    
    
     
       * @return 对象列表
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public Collection<String> 
      keys
      (final String pattern)
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
             
      return redisTemplate.keys(pattern);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      public 
      void 
      incrementCacheMapValue
      (String key,String hKey,long v){
     
    
 
   - 
    
     
    
    
     
              redisTemplate.boundHashOps(key).increment(hKey, v);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
     
      }
     
    
 
  
  
SecurityUtils.java
  
   - 
    
     
    
    
     
      package com.wang.utils;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import com.wang.entity.LoginUser;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.core.Authentication;
     
    
 
   - 
    
     
    
    
     
      import org.springframework.security.core.context.SecurityContextHolder;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      /**
     
    
 
   - 
    
     
    
    
     
       * @author 飞
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
     
      public 
      class 
      SecurityUtils
     
    
 
   - 
    
     
    
    
     
      {
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 获取用户
     
    
 
   - 
    
     
    
    
     
       **/
     
    
 
   - 
    
     
    
    
         
      public 
      static LoginUser 
      getLoginUser
      ()
     
    
 
   - 
    
     
    
    
     
          {
     
    
 
   - 
    
     
    
    
             
      return (LoginUser) getAuthentication().getPrincipal();
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 获取Authentication
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public 
      static Authentication 
      getAuthentication
      () {
     
    
 
   - 
    
     
    
    
             
      return SecurityContextHolder.getContext().getAuthentication();
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      public 
      static Boolean 
      isAdmin
      (){
     
    
 
   - 
    
     
    
    
             
      Long 
      id 
      = getLoginUser().getUser().getId();
     
    
 
   - 
    
     
    
    
             
      return id != 
      null && 
      1L == id;
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      public 
      static Long 
      getUserId
      () {
     
    
 
   - 
    
     
    
    
             
      return getLoginUser().getUser().getId();
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
     
      }
     
    
 
  
  
WebUtils.java
  
   - 
    
     
    
    
     
      package com.wang.utils;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import org.springframework.web.context.request.RequestContextHolder;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      import javax.servlet.ServletContext;
     
    
 
   - 
    
     
    
    
     
      import javax.servlet.http.HttpServletResponse;
     
    
 
   - 
    
     
    
    
     
      import java.io.IOException;
     
    
 
   - 
    
     
    
    
     
      import java.io.UnsupportedEncodingException;
     
    
 
   - 
    
     
    
    
     
      import java.net.URLEncoder;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      /**
     
    
 
   - 
    
     
    
    
     
       * @author 飞
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
     
      public 
      class 
      WebUtils
     
    
 
   - 
    
     
    
    
     
      {
     
    
 
   - 
    
     
    
    
         
      /**
     
    
 
   - 
    
     
    
    
     
       * 将字符串渲染到客户端
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * @param response 渲染对象
     
    
 
   - 
    
     
    
    
     
       * @param string 待渲染的字符串
     
    
 
   - 
    
     
    
    
     
       * @return null
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
         
      public 
      static 
      void 
      renderString
      (HttpServletResponse response, String string) {
     
    
 
   - 
    
     
    
    
             
      try
     
    
 
   - 
    
     
    
    
     
              {
     
    
 
   - 
    
     
    
    
     
                  response.setStatus(
      200);
     
    
 
   - 
    
     
    
    
     
                  response.setContentType(
      "application/json");
     
    
 
   - 
    
     
    
    
     
                  response.setCharacterEncoding(
      "utf-8");
     
    
 
   - 
    
     
    
    
     
                  response.getWriter().print(string);
     
    
 
   - 
    
     
    
    
     
              }
     
    
 
   - 
    
     
    
    
             
      catch (IOException e)
     
    
 
   - 
    
     
    
    
     
              {
     
    
 
   - 
    
     
    
    
     
                  e.printStackTrace();
     
    
 
   - 
    
     
    
    
     
              }
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
         
      public 
      static 
      void 
      setDownLoadHeader
      (String filename, HttpServletResponse response) 
      throws UnsupportedEncodingException {
     
    
 
   - 
    
     
    
    
     
              response.setContentType(
      "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
     
    
 
   - 
    
     
    
    
     
              response.setCharacterEncoding(
      "utf-8");
     
    
 
   - 
    
     
    
    
     
              String fname= URLEncoder.encode(filename,
      "UTF-8").replaceAll(
      "\\+", 
      "%20");
     
    
 
   - 
    
     
    
    
     
              response.setHeader(
      "Content-disposition",
      "attachment; filename="+fname);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
     
      }
     
    
 
  
  
 
 
 
 
转载:https://blog.csdn.net/qq_51438138/article/details/128678530
					