Spring boot + Shiro + Swagger基本登录相关配置(一)

一、相关框架简介
1.1 spring boot
spring boot是由Pivotal团队开发的全新框架,其主要目的是使搭建spring web项目变得简单、快速,能快速进入到项目的业务逻辑开发。其主要的配置是在application命名的文件中,主要有application.properties和application.yml两种配置方式,spring boot项目启动时会默认到项目路径下去寻找application的文件并读取内容。
1.2 Shiro
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。shiro主要由三个主要组建组成:Subject(当前操作用户,不仅仅是人或事物的对象,还可能是线程),SecurityManager(shiro的核心框架,用来管理内部组建实例并提供安全管理的服务),Realm(是shiro和安全数据数据的桥梁,当对用户进行授权或身份验证时,shiro会从配置的Realm中查找用户和其相关权限)。Realm相当于我们开发过程中的dao层,它封装了数据连接的细节。
1.3 Swagger
swagger是目前最受欢迎的Rest Apis文档生成工具之一,它可以生成支持互动类型的API控制台,生成可以在不能平台运行的客户端SDK,Swagger 文档提供了一个方法,使我们可以用指定的 JSON 或者 YAML 摘要来描述你的 API,包括了比如 names、order 等 API 信息等优点。
二、基本接口的提供
以user为列,提供相关接口,具体实现忽略。controller代码如下:

package com.why.greenhouse.back.user.controller;

import com.why.greenhouse.back.config.filter.ShiroProperties;
import com.why.greenhouse.back.user.entity.User;
import com.why.greenhouse.back.user.service.UserService;
import com.why.greenhouse.back.user.model.request.UserRequest;
import com.why.greenhouse.back.user.model.response.UserResponse;

import java.util.List;
import java.util.Map;

import com.why.greenhouse.back.utils.UserUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * 描述:user控制层
 *
 * @author why
 * @date 2018-07-07 14:17:51
 */
@RestController
@RequestMapping(path = "user")
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 描述:根据Id 查询
     *
     * @param id userid
     */
    @GetMapping("findById")
    public UserResponse findById(@RequestParam("id") Long id) throws Exception {
        UserResponse userResponse = userService.queryUserById(id);
        return userResponse;
    }

    /**
     * 描述:创建user
     *
     * @param userRequest
     */
    @PostMapping("add")
    public void add(@RequestBody UserRequest userRequest) throws Exception {
        userService.addUser(userRequest);
    }

    /**
     * 描述:删除user
     *
     * @param id userid
     */
    @DeleteMapping("deleteById")
    public void deleteById(@RequestParam("id") Long id) throws Exception {
        userService.deleteUser(id);
    }

    /**
     * 描述:更新user
     *
     * @param userRequest userRequest
     */
    @PostMapping("update")
    public void update(@RequestBody UserRequest userRequest) throws Exception {
        userService.updateUser(userRequest);
    }
    @Autowired
    private ShiroProperties shiroProperties;
    /**
     * 描述:查询所有user
     */
    @PostMapping("queryAll")
    public List queryAll() throws Exception {
        for(String s : shiroProperties.getFilterRules()){
            System.out.println(s);
        }
        return userService.queryAll();
    }
    /**
     * 描述:查询所有user
     */
    @GetMapping("login")
    public void login(){
//    public void login(@RequestParam(name = "name") String name){
//        User user = userService.queryByName(name);
//        if (user==null){
//            throw new RuntimeException("不存在改用户");
//        }
        System.out.println("的点点滴滴多多多");
    }
}

三、shiro Filter相关代码
添加相关依赖,依赖中有一些自己测试用的包,该功能没有用到



   4.0.0
   com.why
   greenhouse
   pom
   1.0-SNAPSHOT
   
       common
       front
       back
       core
   
   Green House Server
   Green House Server
   
       org.springframework.boot
       spring-boot-starter-parent
       1.5.3.RELEASE
   
   
       UTF-8
       UTF-8
       1.8
       2.7.0
   
   
       
       
           org.springframework.boot
           spring-boot-starter-data-jpa
       
       
       
           org.springframework.boot
           spring-boot-starter-cache
       
       
       
           org.projectlombok
           lombok
           1.16.18
       
       
           org.springframework.boot
           spring-boot-starter-web
       
       
       
           org.springframework.boot
           spring-boot-starter-aop
       
       
       
           org.springframework.boot
           spring-boot-starter-test
           test
       
       
       
           mysql
           mysql-connector-java
           5.1.21
       
       
           io.springfox
           springfox-swagger2
           ${swagger.version}
           
               
                   reflections
                   org.reflections
               
           
       
       
           io.springfox
           springfox-swagger-ui
           ${swagger.version}
       
       
           com.alibaba
           fastjson
           1.2.16
       

       
       
           org.apache.shiro
           shiro-all
           1.2.5
       

       
           com.alibaba
           druid
           RELEASE
       
       
           org.apache.shiro
           shiro-spring
           1.4.0
       
   

通过@Bean方式注入自己定义的拦截和shiro相关的类

package com.why.greenhouse.back.config.filter;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author why
 * 拦截器实例化
 */
@Configuration
@ConditionalOnProperty(name = "shiro.web.enabled", matchIfMissing = true)
public class LoginFilterBean{
    @Autowired
    private ShiroProperties shiroProperties;
    @Bean
    public LoginFilter loginFilter(){
        return new LoginFilter();
    }
    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        return securityManager;
    }

    @ConditionalOnMissingBean
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
        //打印日志便于查看是否进入该拦截器
        System.out.println("LoginFilterBean.shirFilter()");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        Map filterMap = new HashMap<>(20);
        //定义拦截器名称
        filterMap.put("hasToken",new LoginFilter());
        shiroFilterFactoryBean.setFilters(filterMap);
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map filterChainMap = new HashMap<>(20);
        //从配置文件中自定义拦截规则的相关配置信息
        List filters = shiroProperties.getFilterRules();
        if (null!=filters){
            for (String str: filters) {
                String[] temp = str.split("==>");
                if (temp.length != 2) {
                    throw new IllegalStateException("过滤规则配置不正确,格式:url==>filters");
                }
                filterChainMap.put(temp[0],temp[1]);
            }
        }
        //把自己定义的拦截相关规则交给shiro管理
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
        shiroFilterFactoryBean.setLoginUrl("/user/login");
        shiroFilterFactoryBean.setSuccessUrl("/");
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        return shiroFilterFactoryBean;
    }

    /**
     * 加入注解的使用,不加入这个注解不生效
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}

application.yml文件相关配置信息如下:

server:
  tomcat:
    uri-encoding: UTF-8
    max-threads: 3000
  port: 15030
  compression:
    enabled: true
spring:
  datasource:
    password: 1pTVg0ld@1909
    tomcat:
      max-idle: 10
      min-idle: 5
      test-on-borrow: false
      test-while-idle: true
      time-between-eviction-runs-millis: 18800
      validation-query: SELECT 1
      initial-size: 5
      max-wait: 3000
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/why?useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOver
    username: root
    hikari:
      read-only:
  messages:
    cache-seconds: -1
    always-use-message-format: false
    fallback-to-system-locale: true
    basename: i18n/messages
    encoding: UTF-8
  jpa:
    show-sql: true
    database: MYSQL
    generate-ddl: false
    hibernate:
      ddl-auto: update
    properties:
      globally_quoted_identifiers: true
      use_query_cache: false
      hibernate:
        dialect: org.hibernate.dialect.MySQL5Dialect
shiro:
    filter-rules:
        - /swagger-ui.html==>anon
        - /swagger-resources/**==>anon
        - //webjars/**==>anon
        - /v2/**==>anon
        - /user/login/**==>anon
        - /user/queryAll/**==>anon
        - /**==>authc

这个时候还访问不了swagger页面,需要对swagger进行相关的配置,配置类如下:

package com.why.greenhouse.back.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;
import java.util.List;

/**
 * swagger配置
 * @author why
 */
@Configuration
@EnableSwagger2
public class SwaggerConfiguration {
    @Bean
    public Docket createRestApi(){
        //add head start
        ParameterBuilder tokenPar = new ParameterBuilder();
        List pars = new ArrayList<>();
        tokenPar.name("token").description("token").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
        pars.add(tokenPar.build());
        //add head end
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.why.greenhouse"))
                .paths(PathSelectors.any())
                .build()
                .globalOperationParameters(pars);
    }
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("GREEN TOKEN SERVER API information")
                .description("GREEN TOKEN SERVER API information")
                .version("1.0")
                .build();
    }
}

四、代码演示及相关问题修改
这个时候我们访问http://localhost:15030/swagger-ui.html时出现如下情况:

Spring boot + Shiro + Swagger基本登录相关配置(一)_第1张图片
image.png

我们的接口没有了,再看看请求
Spring boot + Shiro + Swagger基本登录相关配置(一)_第2张图片
image.png

和后台日志
Spring boot + Shiro + Swagger基本登录相关配置(一)_第3张图片
image.png

显然是我们请求swagger页面的时候有的页面被拦截器拦截住了,通过请求地址可以看出是在/swagger-resources/configuration请求后跳转到我们拦截之后的接口的,因此对application.yml文件的配置做了如下修改
其中:

  - /swagger-resources/**==>anon

改成

  - /swagger-resources/**/**==>anon

修改之后重新启动项目


Spring boot + Shiro + Swagger基本登录相关配置(一)_第4张图片
image.png

我们的接口出来了,

  • /user/queryAll/**==>anon调用不需要验证的接口:


    Spring boot + Shiro + Swagger基本登录相关配置(一)_第5张图片
    image.png

可以查到内容,再查看需要登录的接口:
后台打印

的点点滴滴多多多

说明进入了我们的拦截指定的接口
五、结束
本项目完全为测试所用,接口没有实际意义,本文只是对shiro Filter做最基本的简单的登录功能验证。踩完后面的坑再写个稍微深入一点的。

你可能感兴趣的:(Spring boot + Shiro + Swagger基本登录相关配置(一))