引入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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>jx.swigger</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--swigger必须的包 start-->
<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>
<!--swigger必须的包 end-->
<!--lombok 不用编写get/set方法 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.67</version>
</dependency>
<!--jwt token 校验的包-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置swigger配置文件
package jx.swigger.demo.config; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; 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; import static springfox.documentation.builders.PathSelectors.regex; @Configuration @EnableSwagger2 class ApiConfig { @Bean public Docket platformApi() { return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).forCodeGeneration(true) .select().apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) .apis(RequestHandlerSelectors.any()) .paths(regex("^.*(?<!error)$")) .build() .securitySchemes(securitySchemes()) .securityContexts(securityContexts()); } private List<ApiKey> securitySchemes() { List<ApiKey> apiKeyList= new ArrayList(); apiKeyList.add(new ApiKey("x-auth-token", "x-auth-token", "header")); return apiKeyList; } private List<SecurityContext> securityContexts() { List<SecurityContext> securityContexts=new ArrayList<>(); securityContexts.add( SecurityContext.builder() .securityReferences(defaultAuth()) .forPaths(regex("^(?!auth).*$")) .build()); return securityContexts; } List<SecurityReference> defaultAuth() { AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; authorizationScopes[0] = authorizationScope; List<SecurityReference> securityReferences=new ArrayList<>(); securityReferences.add(new SecurityReference("Authorization", authorizationScopes)); return securityReferences; } private ApiInfo apiInfo() { return new ApiInfoBuilder().title("壹起成长-API").description("©2020 Copyright. Powered By yiqichengzhang.") // .termsOfServiceUrl("") .contact(new Contact("壹起成长", "", "jiangxiang@17growth-edu.com")) .license("Apache License Version 2.0") .termsOfServiceUrl("http://localhost:8080/swagger-ui.html") .licenseUrl("http://localhost:8080") .license("http://localhost:8080") .version("1.0") .build(); } }
设置拦截器配置,不然配置拦截器失效
package jx.swigger.demo.config; import jx.swigger.demo.handler.AuthenticationInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import java.nio.charset.Charset; import java.util.List; import com.fasterxml.jackson.databind.ObjectMapper; @Configuration public class InterceptorConfig extends WebMvcConfigurationSupport { public void addInterceptors(InterceptorRegistry registry) { // addPathPatterns添加需要拦截的命名空间; // excludePathPatterns添加排除拦截命名空间 registry.addInterceptor(new AuthenticationInterceptor()).addPathPatterns("/**").excludePathPatterns("/register").excludePathPatterns("/login").excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**"); } protected void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("swagger-ui.html") .addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/"); } //以下四个方法解决中文乱码问题 @Bean public HttpMessageConverter<String> responseBodyConverter(){ StringHttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8")); return converter; } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { super.configureMessageConverters(converters); //解决中文乱码 converters.add(responseBodyConverter()); //解决 添加解决中文乱码后 上述配置之后,返回json数据直接报错 500:no convertter for return value of type converters.add(messageConverter()); } @Bean public MappingJackson2HttpMessageConverter messageConverter() { MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setObjectMapper(getObjectMapper()); return converter; } @Bean public ObjectMapper getObjectMapper() { return new ObjectMapper(); } }
设置拦截器
package jx.swigger.demo.handler; import com.alibaba.fastjson.JSON; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.exceptions.JWTVerificationException; import jx.swigger.demo.model.ResponseVo; import jx.swigger.demo.model.User; import jx.swigger.demo.service.UserService; import jx.swigger.demo.tag.PassToken; import jx.swigger.demo.tag.UserLoginToken; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.Method; public class AuthenticationInterceptor extends HandlerInterceptorAdapter { @Autowired UserService userService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception { String token = request.getHeader("x-auth-token"); // 如果不是映射到方法直接通过 if(!(object instanceof HandlerMethod)){ return true; } HandlerMethod handlerMethod=(HandlerMethod)object; Method method=handlerMethod.getMethod(); //检查是否有passtoken注释,有则跳过认证 if (method.isAnnotationPresent(PassToken.class)) { PassToken passToken = method.getAnnotation(PassToken.class); if (passToken.required()) { return true; } } //检查有没有需要用户权限的注解 if (method.isAnnotationPresent(UserLoginToken.class)) { UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class); if (userLoginToken.required()) { // 执行认证 if (token == null) { responseNoToken(response,406,"没有x-auth-token"); return false; } // 获取 token 中的 user id String userId; try { userId = JWT.decode(token).getAudience().get(0); } catch (JWTDecodeException j) { responseNoToken(response,401,"token验证失败"); return false; } User user = userService.findUserById(userId); if (user == null) { responseNoToken(response,406,"用户不存在,请重新登录"); return false; } // 验证 token JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build(); try { jwtVerifier.verify(token); } catch (JWTVerificationException e) { responseNoToken(response,401,"token验证失败"); return false; } return true; } } return true; } public void responseNoToken(HttpServletResponse response,int code,String message) { PrintWriter writer=null; try { String json = JSON.toJSONString(new ResponseVo<String>(code, message,"")); response.setCharacterEncoding("UTF-8"); response.setContentType("application/json; charset=utf-8"); writer = response.getWriter(); writer.write(json); } catch (IOException e) { } finally { if(writer!=null){ writer.close(); } } } }
编写用户服务层
package jx.swigger.demo.service; import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import jx.swigger.demo.model.User; import org.springframework.stereotype.Service; import sun.rmi.runtime.Log; @Service public class UserService { public String getToken(User user){ String token= JWT.create().withAudience(Long.toString(user.getUserId())) .sign(Algorithm.HMAC256(user.getPassword())); return token; } public User findUserById(String userId) { User user = new User(); user.setUserId(1); user.setName("张三"); user.setAge(11); user.setPassword("123456"); user.setSalt("asd"); return user; } }
访问swigger页面 http://localhost:8080/swagger-ui.htm
编写一个测试控制器
package jx.swigger.demo.service; import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import jx.swigger.demo.model.User; import org.springframework.stereotype.Service; import sun.rmi.runtime.Log; @Service public class UserService { public String getToken(User user){ String token= JWT.create().withAudience(Long.toString(user.getUserId())) .sign(Algorithm.HMAC256(user.getPassword())); return token; } public User findUserById(String userId) { User user = new User(); user.setUserId(1); user.setName("张三"); user.setAge(11); user.setPassword("123456"); user.setSalt("asd"); return user; } }
编写需要用的mode
package jx.swigger.demo.model; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data public class ResponseVo<T> { private int code; private String message; private T data; public ResponseVo(int code, String message, T data) { this.code = code; this.message = message; this.data = data; } }
package jx.swigger.demo.model; import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor public class User { private String name; private String password; private int age; private String salt; private long userId; }
package jx.swigger.demo.model; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiResponse; import lombok.Data; @Data @ApiModel("测试mode") public class Test { @ApiModelProperty("返回名称") private String name; @ApiModelProperty("返回年龄") private int age; }
package jx.swigger.demo.model; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel("测试2") public class Test2 { @ApiModelProperty("开放平台Id") private String openId; }
两个注解
package jx.swigger.demo.tag; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface PassToken { boolean required() default true; }
package jx.swigger.demo.tag; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface UserLoginToken { boolean required() default true; }
搭建完成