• Swagger整合Jwt授权配置 Java大师


    Swagger整合Jwt授权配置

    欢迎关注博主公众号「Java大师」, 专注于分享Java领域干货文章http://www.javaman.cn/sb2/swagger-jwt

    一、Swagger入门

    1、什么是Swagger

    Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务,它有着如下的优点:

    1)及时性 (接口变更后,能够及时准确地通知相关前后端开发人员)

    2)规范性 (并且保证接口的规范性,如接口的地址,请求方式,参数及响应格式和错误信息)

    3)一致性 (接口信息一致,不会出现因开发人员拿到的文档版本不一致,而出现分歧)

    4)可测性 (直接在接口文档上进行测试,以方便理解业务)

    2、Swagger生成文档

    1)添加pom.xml依赖

    <!--swagger-->
    <dependency>
    	<groupId>io.springfox</groupId>
    	<artifactId>springfox-swagger2</artifactId>
    	<version>2.7.0</version>
    </dependency>
    <dependency>
    	<groupId>io.springfox</groupId>
    	<artifactId>springfox-swagger-ui</artifactId>
    	<version>2.7.0</version>
    </dependency>
    

    2)创建swagger配置文件

    @Configuration
    @EnableSwagger2
    public class Swagger2Config {
    
        @Bean
        public Docket apiConfig() {
            //创建基于Swagger2的配置文件
            return new Docket(DocumentationType.SWAGGER_2)
                    // 调用apiInfo方法,创建一个ApiInfo实例,里面是展示在文档页面信息内容
                    .apiInfo(apiInfo());
        }
        private ApiInfo apiInfo() {
            return new ApiInfoBuilder()
                    //标题
                    .title("接口文档")
                    //描述
                    .description("接口文档")
                    //版本
                    .version("1.0")
                    //作者信息
                    .contact(new Contact("java大师", "http://localhost:8081", "xxx@qq.com"))
                    .build();
        }
    }
    

    3)启动程序

    访问路径:http://localhost:8081/swagger-ui.html ,出现生成的文档页面。

    在这里插入图片描述

    此为原生界面,很难看,所以我们需要引入swagger-bootstrap-ui,也就是Knife4j的前身

    4)使用Knife4j

    a)添加pom.xml依赖

    <dependency>
    	<groupId>com.github.xiaoymin</groupId>
    	<artifactId>knife4j-spring-boot-starter</artifactId>
    	<version>2.0.7</version>
    </dependency>
    

    b)开启Swagger2配置

    import java.util.ArrayList;
    import java.util.List;
    
    @Configuration
    @EnableSwagger2
    public class Swagger2Config {
        @Bean
        public Docket createRestApi() {
            return new Docket(DocumentationType.SWAGGER_2)
                    .pathMapping("/")
                    .apiInfo(apiInfo())
                    .select()
                    //swagger要扫描的包路径
                    .apis(RequestHandlerSelectors.basePackage("com.dsblog.server.controller"))
                    .paths(PathSelectors.any())
                    .build()
        }
    
        private ApiInfo apiInfo() {
            return new ApiInfoBuilder().title("dsblog接口文档")
                    .contact(new Contact("java大师","http://localhost:8081/doc.html","fry000@qq.com"))
                    .version("1.0").description("dsblog接口文档").build();
        }
    

    b)重启服务

    访问地址:http://localhost:8081/doc.html,这个ui界面看起来就更美观,更符合国人的使用习惯

    在这里插入图片描述

    二、Swagger整合Jwt

    1、添加pom.xml依赖

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <parent>
        <groupId>com.dsblog</groupId>
        <artifactId>dsblog</artifactId>
        <version>0.0.1-SNAPSHOT</version>
      </parent>
    
      <groupId>com.dsblog</groupId>
      <artifactId>dsblog-server</artifactId>
      <version>0.0.1-SNAPSHOT</version>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
      </properties>
    
      <dependencies>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
          <optional>true</optional>
        </dependency>
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <scope>runtime</scope>
        </dependency>
        <dependency>
          <groupId>com.baomidou</groupId>
          <artifactId>mybatis-plus-boot-starter</artifactId>
          <version>3.4.0</version>
        </dependency>
        <dependency>
          <groupId>org.freemarker</groupId>
          <artifactId>freemarker</artifactId>
          <version>2.3.31</version>
        </dependency>
        <dependency>
          <groupId>com.baomidou</groupId>
          <artifactId>mybatis-plus-generator</artifactId>
          <version>3.3.2</version>
        </dependency>
        <dependency>
          <groupId>io.swagger</groupId>
          <artifactId>swagger-annotations</artifactId>
          <version>1.5.20</version>
        </dependency>
        <!--swagger-->
        <dependency>
          <groupId>io.springfox</groupId>
          <artifactId>springfox-swagger2</artifactId>
          <version>2.7.0</version>
        </dependency>
        <dependency>
          <groupId>io.springfox</groupId>
          <artifactId>springfox-swagger-ui</artifactId>
          <version>2.7.0</version>
        </dependency>
        <dependency>
          <groupId>com.github.xiaoymin</groupId>
          <artifactId>knife4j-spring-boot-starter</artifactId>
          <version>2.0.7</version>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-security</artifactId>
          <version>2.3.6.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>io.jsonwebtoken</groupId>
          <artifactId>jjwt</artifactId>
          <version>0.9.1</version>
        </dependency>
      </dependencies>
    </project>
    

    2、创建Swagger2Config配置文件

    package com.dsblog.server.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import springfox.documentation.builders.ApiInfoBuilder;
    import springfox.documentation.builders.PathSelectors;
    import springfox.documentation.builders.RequestHandlerSelectors;
    import springfox.documentation.service.*;
    import springfox.documentation.spi.DocumentationType;
    import springfox.documentation.spi.service.contexts.SecurityContext;
    import springfox.documentation.spring.web.plugins.Docket;
    import springfox.documentation.swagger2.annotations.EnableSwagger2;
    
    import java.util.ArrayList;
    import java.util.List;
    
    @Configuration
    @EnableSwagger2
    public class Swagger2Config {
        @Bean
        public Docket createRestApi() {
            return new Docket(DocumentationType.SWAGGER_2)
                    .pathMapping("/")
                    .apiInfo(apiInfo())
                    .select()
                    //swagger要扫描的包路径
                    .apis(RequestHandlerSelectors.basePackage("com.dsblog.server.controller"))
                    .paths(PathSelectors.any())
                    .build()
                    .securityContexts(securityContexts())
                    .securitySchemes(securitySchemes());
        }
    
        private ApiInfo apiInfo() {
            return new ApiInfoBuilder().title("dsblog接口文档")
                    .contact(new Contact("java大师","http://localhost:8081/doc.html","fry000@qq.com"))
                    .version("1.0").description("dsblog接口文档").build();
        }
    
        private List<SecurityContext> securityContexts() {
            //设置需要登录认证的路径
            List<SecurityContext> result = new ArrayList<>();
            result.add(getContextByPath("/.*"));
            return result;
        }
    	
      //通过pathRegex获取SecurityContext对象
        private SecurityContext getContextByPath(String pathRegex) {
            return SecurityContext.builder()
                    .securityReferences(defaultAuth())
                    .forPaths(PathSelectors.regex(pathRegex))
                    .build();
        }
    
      	//默认为全局的SecurityReference对象
        private List<SecurityReference> defaultAuth() {
            List<SecurityReference> result = new ArrayList<>();
            AuthorizationScope authorizationScope = new AuthorizationScope("global",
                    "accessEverything");
            AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
            authorizationScopes[0] = authorizationScope;
            result.add(new SecurityReference("Authorization", authorizationScopes));
            return result;
        }
    
        private List<ApiKey> securitySchemes() {
            //设置请求头信息
            List<ApiKey> result = new ArrayList<>();
            ApiKey apiKey = new ApiKey("Authorization", "Authorization", "header");
            result.add(apiKey);
            return result;
        }
    }
    

    3、创建SecurityConfig配置文件

    package com.dsblog.server.config.security;
    
    import com.dsblog.server.model.User;
    import com.dsblog.server.service.IUserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.builders.WebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.config.http.SessionCreationPolicy;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
    
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private IUserService userService;
        @Autowired
        private RestAuthorizationEntryPoint restAuthorizationEntryPoint;
        @Autowired
        private RestAccessDeniedHandler restAccessDeniedHandler;
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
        }
    
      	//主要的配置文件,antMatchers匹配的路径,全部忽略,不进行JwtToken的认证
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers(
                    "/login",
                    "/logout",
                    "/css/**",
                    "/js/**",
                    "/index.html",
                    "favicon.ico",
                    "/doc.html",
                    "/webjars/**",
                    "/swagger-resources/**",
                    "/v2/api-docs/**"
            );
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable()
                    .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                    .authorizeRequests()
                    .anyRequest().authenticated()
                    .and()
                    .headers()
                    .cacheControl();
            //添加Jwt登录授权拦截器
            http.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
            //添加未登录和未授权结果返回
            http.exceptionHandling()
                    .accessDeniedHandler(restAccessDeniedHandler)
                    .authenticationEntryPoint(restAuthorizationEntryPoint);
        }
    
        @Override
        @Bean
        public UserDetailsService userDetailsService(){
            return username -> {
                User user = userService.getUserByUsername(username);
                if(null!=user){
                    return user;
                }
                return null;
            };
        }
    
        @Bean
        public PasswordEncoder passwordEncoder(){
            return new BCryptPasswordEncoder();
        }
    
        @Bean
        public  JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter(){
            return new JwtAuthenticationTokenFilter();
        }
    }
    

    4、创建测试Controller,其中/login登录和/logout退出方法不需要Authorize验证,和上面的重写方法configure(WebSecurity web)匹配,user/info方法需要Authorize验证才能进行访问

    package com.dsblog.server.controller;
    
    import com.dsblog.server.model.ResultBean;
    import com.dsblog.server.model.User;
    import com.dsblog.server.model.UserLoginParam;
    import com.dsblog.server.service.IUserService;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpServletRequest;
    import java.security.Principal;
    
    @Api(tags = "LoginController")
    @RestController
    public class LoginController {
    
        @Autowired
        private IUserService userService;
    
        @ApiOperation("登录")
        @PostMapping("/login")
        public ResultBean login(@RequestBody UserLoginParam userLoginParam, HttpServletRequest request){
            return userService.login(userLoginParam.getUsername(),userLoginParam.getPassword(),request);
        }
    
        @ApiOperation("退出")
        @PostMapping("/logout")
        public ResultBean logout(){
            return ResultBean.success("退出成功!");
        }
    
        @ApiOperation("获取当前登录用户")
        @GetMapping("/user/info")
        public User getUserInfo(Principal principal){
            if(null == principal){
                return null;
            }
            String username = principal.getName();
            User user = userService.getUserByUsername(username);
            user.setPassword(null);
            return user;
        }
    }
    

    5、重启程序,输入http://localhost:8081/doc.html
    在这里插入图片描述

    6、测试

    1)首先调用/user/info,会看到提示未登录,请先登录。需要登录授权才能够进行方法的测试
    在这里插入图片描述

    2)接着调用登录请求,输入用户名和密码获取JwtToken
    在这里插入图片描述

    3)获取token后,监测网络,发现会将Authorization放入请求头部发送到后台
    在这里插入图片描述

    4)Authorize加入Bearer和JwtToken
    在这里插入图片描述

    5)携带token发送到后台获取用户信息,验证通过
    在这里插入图片描述

  • 相关阅读:
    使用zoom.js 给博客园的图片添加点击图片放大功能
    html上传多图并预览
    html页面选择图片上传时实现图片预览功能
    html实现点击图片放大功能
    layui常用功能
    七牛云上传与删除图片
    寻找七牛云存储配置参数
    TP5之发送邮件
    TP5之一次选择多张图片并预览
    TP5之页面跳转样式
  • 原文地址:https://www.cnblogs.com/dalaba/p/16014525.html
Copyright © 2020-2023  润新知