当前位置:   article > 正文

基于SpringBoot2开发WebApi(六)JWT(json web token)集成_jwt getaudience

jwt getaudience

1.前言

1.1.JWT说明

JWT全程JSON Web Token,是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名。

1.2.什么情况下需要用JWT

  • Authorization (授权) : 这是使用JWT的最常见场景。一旦用户登录,后续每个请求都将包含JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录是现在广泛使用的JWT的一个特性,因为它的开销很小,并且可以轻松地跨域使用。
  • Information Exchange (信息交换) : 对于安全的在各方之间传输信息而言,JSON Web Token无疑是一种很好的方式。因为JWT可以被签名,例如,用公钥/私钥对,你可以确定发送人就是它们所说的那个人。另外,由于签名是使用头和有效负载计算的,您还可以验证内容没有被篡改。

1.3.JWT结构说明

JSON Web Token由三部分组成,它们之间用圆点(.)连接。这三部分分别是:

  • Header:JWT头
  • Payload:有效载荷
  • Signature:签名

结构是这样的:xxxxxx.yyyyyy.zzzzzz

例如:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOlsiMSIsImFkbWluIiwiMSJdLCJleHAiOjE2MjMwNzUyMzcsImlhdCI6MTYyMzA0NjQzN30.pT5NgZCkfN2WwQS8rp1Scifa07KbuvZbXO8y8596ACg

2.集成说明

2.1引入依赖

  1. <dependency>
  2. <groupId>com.auth0</groupId>
  3. <artifactId>java-jwt</artifactId>
  4. <version>3.4.0</version>
  5. </dependency>

2.2.定义Token工具类

TokenUtil
  1. package com.xxxxxx.sim.utils;
  2. import com.auth0.jwt.JWT;
  3. import com.xxxxxx.sim.model.AdminUser;
  4. import org.springframework.boot.autoconfigure.kafka.KafkaProperties;
  5. import org.springframework.web.context.request.RequestContextHolder;
  6. import org.springframework.web.context.request.ServletRequestAttributes;
  7. import javax.servlet.http.HttpServletRequest;
  8. import java.math.BigInteger;
  9. import java.util.List;
  10. /**
  11. * Token方法封装
  12. * @author xxxx
  13. * @date 20200428
  14. */
  15. public class TokenUtil {
  16. /**
  17. * 获取Token里面的UserId
  18. * @return
  19. */
  20. public static String getTokenUserId() {
  21. // 从 http 请求头中取出 token
  22. String token = getRequest().getHeader("token");
  23. String userId = JWT.decode(token).getAudience().get(0);
  24. return userId;
  25. }
  26. /**
  27. * 获取Token里面的UserName
  28. * @return
  29. */
  30. public static String getTokenUseName(){
  31. // 从 http 请求头中取出 token
  32. String token = getRequest().getHeader("token");
  33. String userName = JWT.decode(token).getAudience().get(1);
  34. return userName;
  35. }
  36. /**
  37. * 获取request
  38. *
  39. * @return
  40. */
  41. public static HttpServletRequest getRequest() {
  42. ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
  43. .getRequestAttributes();
  44. return requestAttributes == null ? null : requestAttributes.getRequest();
  45. }
  46. }

2.3.定义注解

@CheckToken需要验证Token注解
  1. package com.xxxxxx.sim.annotation;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. /**
  7. * 需要验证Token
  8. * @author xxxxxx
  9. * @date 20200428
  10. */
  11. @Target({ElementType.METHOD, ElementType.TYPE})
  12. @Retention(RetentionPolicy.RUNTIME)
  13. public @interface CheckToken {
  14. boolean required() default true;
  15. }
@PassToken跳过Token验证注解
  1. package com.xxxxxx.sim.annotation;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. /**
  7. * 跳过验证
  8. * @author xxxxxx
  9. * @date 20200428
  10. */
  11. @Target({ElementType.METHOD, ElementType.TYPE})
  12. @Retention(RetentionPolicy.RUNTIME)
  13. public @interface PassToken {
  14. boolean required() default true;
  15. }

需要验证Token注解

2.4.定义Token拦截器

AuthenticationInterceptor
  1. package com.xxxxxx.sim.utils;
  2. import com.auth0.jwt.JWT;
  3. import com.auth0.jwt.JWTVerifier;
  4. import com.auth0.jwt.algorithms.Algorithm;
  5. import com.auth0.jwt.exceptions.JWTDecodeException;
  6. import com.auth0.jwt.exceptions.JWTVerificationException;
  7. import com.xxxxxx.sim.annotation.CheckToken;
  8. import com.xxxxxx.sim.annotation.PassToken;
  9. import com.xxxxxx.sim.model.AdminUser;
  10. import com.xxxxxx.sim.service.AdminUserService;
  11. import org.springframework.beans.factory.annotation.Autowired;
  12. import org.springframework.web.method.HandlerMethod;
  13. import org.springframework.web.servlet.HandlerInterceptor;
  14. import org.springframework.web.servlet.ModelAndView;
  15. import javax.servlet.http.HttpServletRequest;
  16. import javax.servlet.http.HttpServletResponse;
  17. import java.lang.reflect.Method;
  18. import java.math.BigInteger;
  19. /**
  20. * Token拦截器
  21. * @author xxxxxx
  22. * @date 20200428
  23. */
  24. public class AuthenticationInterceptor implements HandlerInterceptor {
  25. @Autowired
  26. private AdminUserService adminUserService;
  27. @Override
  28. public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
  29. // 从 http 请求头中取出 token
  30. String token = httpServletRequest.getHeader("token");
  31. // 如果不是映射到方法直接通过
  32. if(!(object instanceof HandlerMethod)){
  33. return true;
  34. }
  35. HandlerMethod handlerMethod=(HandlerMethod)object;
  36. Method method=handlerMethod.getMethod();
  37. //检查是否有PassToken注释,有则跳过认证
  38. if (method.isAnnotationPresent(PassToken.class)) {
  39. PassToken passToken = method.getAnnotation(PassToken.class);
  40. if (passToken.required()) {
  41. return true;
  42. }
  43. }
  44. //检查有没有需要用户权限的注解
  45. if (method.isAnnotationPresent(CheckToken.class)) {
  46. CheckToken checkToken = method.getAnnotation(CheckToken.class);
  47. if (checkToken.required()) {
  48. // 执行认证
  49. if (token == null) {
  50. return false;
  51. }
  52. // 获取 token 中的 user id
  53. String userId;
  54. try {
  55. userId = JWT.decode(token).getAudience().get(0);
  56. } catch (JWTDecodeException j) {
  57. return false;
  58. }
  59. AdminUser user = adminUserService.queryAdminUserById(new BigInteger(userId));
  60. if (user == null) {
  61. return false;
  62. }
  63. // 验证 token
  64. JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassWord())).build();
  65. try {
  66. jwtVerifier.verify(token);
  67. } catch (JWTVerificationException e) {
  68. return false;
  69. }
  70. return true;
  71. }
  72. }
  73. return true;
  74. }
  75. @Override
  76. public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
  77. }
  78. @Override
  79. public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
  80. }
  81. }

2.5.初始化拦截器

  1. package com.xxxxxx.sim.configuration;
  2. import com.xxxxxx.sim.utils.AuthenticationInterceptor;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.format.FormatterRegistry;
  6. import org.springframework.http.converter.HttpMessageConverter;
  7. import org.springframework.validation.MessageCodesResolver;
  8. import org.springframework.validation.Validator;
  9. import org.springframework.web.method.support.HandlerMethodArgumentResolver;
  10. import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
  11. import org.springframework.web.servlet.HandlerExceptionResolver;
  12. import org.springframework.web.servlet.config.annotation.*;
  13. import java.util.List;
  14. /**
  15. * 新建Token拦截器
  16. * @author xxxxxxx
  17. * @date 20200429
  18. */
  19. @Configuration
  20. public class InterceptorConfig implements WebMvcConfigurer {
  21. @Override
  22. public void addInterceptors(InterceptorRegistry registry) {
  23. registry.addInterceptor(authenticationInterceptor())
  24. .addPathPatterns("/**");
  25. }
  26. @Bean
  27. public AuthenticationInterceptor authenticationInterceptor() {
  28. return new AuthenticationInterceptor();
  29. }
  30. @Override
  31. public void addArgumentResolvers(List<HandlerMethodArgumentResolver> arg0) {
  32. // TODO Auto-generated method stub
  33. }
  34. @Override
  35. public void addCorsMappings(CorsRegistry arg0) {
  36. // TODO Auto-generated method stub
  37. }
  38. @Override
  39. public void addFormatters(FormatterRegistry arg0) {
  40. // TODO Auto-generated method stub
  41. }
  42. @Override
  43. public void addResourceHandlers(ResourceHandlerRegistry arg0) {
  44. // TODO Auto-generated method stub
  45. }
  46. @Override
  47. public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> arg0) {
  48. // TODO Auto-generated method stub
  49. }
  50. @Override
  51. public void addViewControllers(ViewControllerRegistry arg0) {
  52. // TODO Auto-generated method stub
  53. }
  54. @Override
  55. public void configureAsyncSupport(AsyncSupportConfigurer arg0) {
  56. // TODO Auto-generated method stub
  57. }
  58. @Override
  59. public void configureContentNegotiation(ContentNegotiationConfigurer arg0) {
  60. // TODO Auto-generated method stub
  61. }
  62. @Override
  63. public void configureDefaultServletHandling(DefaultServletHandlerConfigurer arg0) {
  64. // TODO Auto-generated method stub
  65. }
  66. @Override
  67. public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> arg0) {
  68. // TODO Auto-generated method stub
  69. }
  70. @Override
  71. public void configureMessageConverters(List<HttpMessageConverter<?>> arg0) {
  72. // TODO Auto-generated method stub
  73. }
  74. @Override
  75. public void configurePathMatch(PathMatchConfigurer arg0) {
  76. // TODO Auto-generated method stub
  77. }
  78. @Override
  79. public void configureViewResolvers(ViewResolverRegistry arg0) {
  80. // TODO Auto-generated method stub
  81. }
  82. @Override
  83. public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> arg0) {
  84. // TODO Auto-generated method stub
  85. }
  86. @Override
  87. public void extendMessageConverters(List<HttpMessageConverter<?>> arg0) {
  88. // TODO Auto-generated method stub
  89. }
  90. @Override
  91. public MessageCodesResolver getMessageCodesResolver() {
  92. // TODO Auto-generated method stub
  93. return null;
  94. }
  95. @Override
  96. public Validator getValidator() {
  97. // TODO Auto-generated method stub
  98. return null;
  99. }
  100. }

3.Token使用

3.1.定义token使用Service

  1. package com.xxxxxx.sim.service;
  2. import com.auth0.jwt.JWT;
  3. import com.auth0.jwt.algorithms.Algorithm;
  4. import com.xxxxxx.sim.model.AdminUser;
  5. import org.springframework.stereotype.Service;
  6. import java.util.Date;
  7. /**
  8. * 获取Token Service
  9. * @author xxxxxx
  10. */
  11. @Service
  12. public class TokenService {
  13. /**
  14. * 获取Token
  15. * @param user
  16. * @return
  17. */
  18. public String getToken(AdminUser user) {
  19. Date start = new Date();
  20. //8小时有效时间
  21. long currentTime = System.currentTimeMillis() + 8*60* 60 * 1000;
  22. Date end = new Date(currentTime);
  23. String token = "";
  24. token = JWT.create().withAudience(user.getId().toString()).withIssuedAt(start).withExpiresAt(end)
  25. .sign(Algorithm.HMAC256(user.getPassWord()));
  26. return token;
  27. }
  28. }

3.2.登录Controller生成Token

  1. package com.xxxxxx.sim.controller;
  2. import com.xxxxxx.sim.base.Result;
  3. import com.xxxxxx.sim.base.ResultEnum;
  4. import com.xxxxxx.sim.base.ResultGenerator;
  5. import com.xxxxxx.sim.model.AdminUser;
  6. import com.xxxxxx.sim.service.AdminUserService;
  7. import com.xxxxxx.sim.service.TokenService;
  8. import io.swagger.annotations.Api;
  9. import io.swagger.annotations.ApiOperation;
  10. import io.swagger.annotations.ApiResponse;
  11. import io.swagger.annotations.ApiResponses;
  12. import org.springframework.beans.factory.annotation.Autowired;
  13. import org.springframework.web.bind.annotation.RequestMapping;
  14. import org.springframework.web.bind.annotation.RequestMethod;
  15. import org.springframework.web.bind.annotation.RequestParam;
  16. import org.springframework.web.bind.annotation.RestController;
  17. import javax.servlet.http.Cookie;
  18. import javax.servlet.http.HttpServletResponse;
  19. /**
  20. * @author xxxxxx
  21. */
  22. @Api(tags = "登录")
  23. @RestController
  24. public class LoginController {
  25. @Autowired
  26. private AdminUserService adminUserService;
  27. @Autowired
  28. private TokenService tokenService;
  29. @ApiOperation(value = "登陆", notes = "登陆")
  30. @ApiResponses({
  31. @ApiResponse(code = 200,message = "成功",response = AdminUser.class),
  32. })
  33. @RequestMapping(value = "/login" ,method = RequestMethod.GET)
  34. public Result<Object> login(@RequestParam String userName, @RequestParam String password, HttpServletResponse response){
  35. AdminUser adminUser=adminUserService.queryAdminUserListByUserName(userName);
  36. if(adminUser!=null)
  37. {
  38. if(adminUser.getPassWord().equals(password))
  39. {
  40. String token = tokenService.getToken(adminUser);
  41. Cookie cookie = new Cookie("token", token);
  42. cookie.setPath("/");
  43. response.addCookie(cookie);
  44. //将token返回前端
  45. adminUser.setUserToken(token);
  46. //将密码置空,不返回给前端
  47. adminUser.setPassWord("");
  48. return ResultGenerator.success(adminUser);
  49. }else
  50. {
  51. return ResultGenerator.failure(ResultEnum.PASSWORD_ERROR);
  52. }
  53. }else
  54. {
  55. return ResultGenerator.failure(ResultEnum.USER_NOT_EXISTS);
  56. }
  57. }
  58. }

3.3.接口需要验证Token

  1. @CheckToken
  2. @ApiOperation(value = "用户列表查询", notes = "用户列表查询")
  3. @ApiImplicitParams({
  4. @ApiImplicitParam(name = "key",value = "查询条件"),
  5. @ApiImplicitParam(name = "pageNum",value = "当前页",required = true),
  6. @ApiImplicitParam(name = "pageSize",value = "每页显示条数",required = true),
  7. @ApiImplicitParam(name = "roleId",value = "角色id",required = true)
  8. })
  9. @ApiResponses({
  10. @ApiResponse(code = 200,message = "成功",response = AdminUser.class),
  11. })
  12. @PostMapping(value = "queryAdminUserList")
  13. public Result<Object> queryAdminUserList(String key, int pageNum, int pageSize,BigInteger roleId){
  14. try {
  15. //判空
  16. if(roleId.longValue() <= 0){
  17. return ResultGenerator.failure(ResultEnum.Param_Error) ;
  18. }
  19. PageResult pageUserList = adminUserService.queryAdminUserList(key,pageNum,pageSize,roleId);
  20. return ResultGenerator.success("成功",pageUserList);
  21. } catch (Exception e) {
  22. e.printStackTrace();
  23. return ResultGenerator.error("失败:" + e.getMessage());
  24. }
  25. }

在接口方法上加上@CheckToken注解即可

4.最后再Swagger2上增加token传入的说明

  1. package com.xxxxxx.sim.configuration;
  2. import com.xxxxxx.sim.base.ResultEnum;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.web.bind.annotation.RequestMethod;
  6. import springfox.documentation.builders.*;
  7. import springfox.documentation.schema.ModelRef;
  8. import springfox.documentation.service.ApiInfo;
  9. import springfox.documentation.service.Parameter;
  10. import springfox.documentation.service.ResponseMessage;
  11. import springfox.documentation.spi.DocumentationType;
  12. import springfox.documentation.spring.web.plugins.Docket;
  13. import springfox.documentation.swagger2.annotations.EnableSwagger2;
  14. import java.util.ArrayList;
  15. import java.util.Arrays;
  16. import java.util.List;
  17. /**
  18. * <p>Swagger2配置类</p>
  19. * @author xxxxxx
  20. * @date 20200429
  21. */
  22. @Configuration
  23. @EnableSwagger2
  24. public class SwaggerConfig {
  25. /**
  26. * 创建API应用
  27. * apiInfo() 增加API相关信息
  28. * 通过select()函数返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现,
  29. * 本例采用指定扫描的包路径来定义指定要建立API的目录。
  30. *
  31. * @return
  32. */
  33. @Bean
  34. public Docket createRestApi() {
  35. //添加全局响应状态码
  36. List<ResponseMessage> responseMessageList = new ArrayList<>();
  37. Arrays.stream(ResultEnum.values()).forEach(errorEnums -> {
  38. responseMessageList.add(
  39. new ResponseMessageBuilder().code(errorEnums.getCode()).message(errorEnums.getMessage()).responseModel(
  40. new ModelRef(errorEnums.getMessage())).build()
  41. );
  42. });
  43. ParameterBuilder aParameterBuilder = new ParameterBuilder();
  44. aParameterBuilder.name("token").description("token验证信息").modelRef(new ModelRef("String")).parameterType("header").build();
  45. List<Parameter> aParameters = new ArrayList<Parameter>();
  46. aParameters.add(aParameterBuilder.build());
  47. return new Docket(DocumentationType.SWAGGER_2)
  48. // 添加全局响应状态码
  49. .globalResponseMessage(RequestMethod.GET, responseMessageList)
  50. .globalResponseMessage(RequestMethod.POST, responseMessageList)
  51. .globalResponseMessage(RequestMethod.PUT, responseMessageList)
  52. .globalResponseMessage(RequestMethod.DELETE, responseMessageList)
  53. .apiInfo(apiInfo())
  54. .select()
  55. .apis(RequestHandlerSelectors.basePackage("com.jointcontrols.sim.controller"))
  56. .paths(PathSelectors.any())
  57. .build()
  58. .useDefaultResponseMessages(false)
  59. .globalOperationParameters(aParameters);
  60. }
  61. /**
  62. * 创建该API的基本信息(这些基本信息会展现在文档页面中)
  63. * 访问地址:http://项目实际地址/swagger-ui.html
  64. *
  65. * @return
  66. */
  67. private ApiInfo apiInfo() {
  68. return new ApiInfoBuilder()
  69. .title("SIM Manager APIs")
  70. .description("SIM卡管理接口文档")
  71. .termsOfServiceUrl("http://www.baidu.com")
  72. .version("1.0.0")
  73. .build();
  74. }
  75. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/201254
推荐阅读
相关标签
  

闽ICP备14008679号