使用 jjwt 做 token 认证


在这里插入图片描述

  采用 springcloud 微服务。

  创建父工程。


// pom.xml 部分代码

	<packaging>pom</packaging>

	<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
    </parent>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR5</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>


  创建 EurekaServer。采用 module 的方式创建。


// pom.xml

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>


// application.yml

server:
  port: 8080

spring:
  application:
    name: openapi-eureka
#  security:
#    user:
#      name:
#      password:

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8080/eureka
    fetch-registry: false
    register-with-eureka: false


// EurekaApplication.java

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }
}

// 查看注册信息
http://localhost:8080/

  创建 auth 工程,在登录接口中生成 jjwt。


// pom.xml

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

// application.yml

server:
  port: 8083

spring:
  application:
    name: openapi-auth

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8080/eureka


// AuthApplication.java

@SpringBootApplication
@EnableEurekaClient
public class AuthApplication {

    public static void main(String[] args) {
        SpringApplication.run(AuthApplication.class, args);
    }

}


// User.java

@Data
public class User {

    private String username;

    private  String password;

}

// BaseResultBean.java

@Data
public class BaseResultBean {

    private String msg;
    private String code;

}

// AuthController.java

@RestController
public class AuthController {

    @RequestMapping(value = "/login", method = {RequestMethod.POST})
    public BaseResultBean login(@RequestBody User user, HttpServletResponse response) {
        BaseResultBean resultBean = new BaseResultBean();
        if ("admin".equalsIgnoreCase(user.getUsername()) && "admin".equalsIgnoreCase(user.getPassword())) {
            resultBean.setCode("200");
            resultBean.setMsg("登录成功");


            Instant now = Instant.now();
            String jwt = Jwts.builder()
                    .setSubject(user.getUsername()) // 设置用户
                    .setIssuedAt(Date.from(now))    // 设置 token 有效期开始时间
                    .setExpiration(Date.from(now.plusSeconds(3600)))  // 结束时间
                    .claim("id","1001")       // token 携带参数
                    .claim("username",user.getUsername())
                    .signWith(SignatureAlgorithm.HS256, "jwtPassword")
                    .compact();

            System.out.println("jwt: " + jwt);

            // 在 token 中响应出去
            response.setHeader("token", jwt);

            // 存储最新的 token

        } else {
            resultBean.setCode("201");
            resultBean.setMsg("登录失败");
        }
        return resultBean;
    }

}

  在 zuul 过滤器中验证请求是否携带了正确的 token。


// pom.xml

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>


// application.yml

server:
  port: 8085
spring:
  application:
    name: openapi-gateway
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8080/eureka

# zuul actuator 监控,http://localhost/actuator/routes
management:
  endpoints:
    web:
      exposure:
        include: "*"
#zuul:
#  ignored-services: "*"


// GatewayController.java

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class GatewayController {

    public static void main(String[] args) {
        SpringApplication.run(GatewayController.class, args);
    }

}


// JwtFilter.java

@Component
public class JwtFilter extends ZuulFilter {

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return 1;
    }

    @Override
    public boolean shouldFilter() {
        return RequestContext.getCurrentContext().sendZuulResponse();
//        return false;
    }

    @Override
    public Object run() throws ZuulException {

        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
        HttpServletResponse response = currentContext.getResponse();

        String jwt = request.getHeader("token");

        try {
            Claims claims = Jwts.parser().setSigningKey("jwtPassword").parseClaimsJws(jwt).getBody();
            String subject = claims.getSubject();
            Object id = claims.get("id");
            Object username = claims.get("username");
            System.out.println("subject: " + subject);
            System.out.println("id: " + id);
            System.out.println("username: " + username);

            // 比对是否最新的 token ,否则 throw

        } catch (Exception e) {
            e.printStackTrace();

            // 不放行
            currentContext.setSendZuulResponse(false);

            BaseResultBean resultBean = new BaseResultBean();
            resultBean.setCode("202");
            resultBean.setMsg("登录认证失败,请重新登录。");

            response.setContentType("application/json;charset=utf-8");

            try {
                String s = objectMapper.writeValueAsString(resultBean);
                currentContext.setResponseBody(s);
            } catch (JsonProcessingException ex) {
                ex.printStackTrace();
            }


        }


        return null;
    }
}


  Postman 验证。
  先拿到 jjwt 字符串。
在这里插入图片描述

  再发送携带 token 的请求。
在这里插入图片描述

  注意,每次登录请求时都会得到一个新的 jjwt,但之前未过期的 jjwt 仍然能通过认证,所以在认证时还应该判断 jjwt 是否最新。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值