Jwt在Java项目中的简单实际应用
1.什么是jwt
2.Jwt在javaweb项目中的简单使用
第一步:引入maven依赖
- <!--引入JWT依赖,由于是基于Java,所以需要的是java-jwt-->
- <dependency>
- <groupId>io.jsonwebtoken</groupId>
- <artifactId>jjwt</artifactId>
- <version>0.9.1</version>
- </dependency>
- <dependency>
- <groupId>com.auth0</groupId>
- <artifactId>java-jwt</artifactId>
- <version>3.4.0</version>
- </dependency>
第二步:创建两个注解,拦截器通过注释区分是否进行权限拦截(详情参考上一篇文章JWT在JAVAWEB项目中的应用核心步骤解读 https://www.cnblogs.com/jimisun/p/9480886.html)
- package com.pjb.springbootjjwt.jimisun;
- 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 LoginToken {
- boolean required() default true;
- }
- package com.pjb.springbootjjwt.jimisun;
- 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 CheckToken {
- boolean required() default true;
- }
第三步:编写JwtUtil工具类(生成token,解析token,校验token)
- package com.pjb.springbootjjwt.jimisun;
- import io.jsonwebtoken.Claims;
- import io.jsonwebtoken.JwtBuilder;
- import io.jsonwebtoken.Jwts;
- import io.jsonwebtoken.SignatureAlgorithm;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.UUID;
- /**
- * @Author:jimisun
- * @Description:
- * @Date:Created in 14:08 2018/8/15
- * @Modified By:
- */
- public class JwtUtil {
- /**
- * 用户登录成功后生成Jwt
- * 使用Hs256算法 私匙使用用户密码
- *
- * @param ttlMillis jwt过期时间
- * @param user 登录成功的user对象
- * @return
- */
- public static String createJWT(long ttlMillis, User user) {
- //指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。
- SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
- //生成JWT的时间
- long nowMillis = System.currentTimeMillis();
- Date now = new Date(nowMillis);
- //创建payload的私有声明(根据特定的业务需要添加,如果要拿这个做验证,一般是需要和jwt的接收方提前沟通好验证方式的)
- Map<String, Object> claims = new HashMap<String, Object>();
- claims.put("id", user.getId());
- claims.put("username", user.getUsername());
- claims.put("password", user.getPassword());
- //生成签名的时候使用的秘钥secret,这个方法本地封装了的,一般可以从本地配置文件中读取,切记这个秘钥不能外露哦。它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。
- String key = user.getPassword();
- //生成签发人
- String subject = user.getUsername();
- //下面就是在为payload添加各种标准声明和私有声明了
- //这里其实就是new一个JwtBuilder,设置jwt的body
- JwtBuilder builder = Jwts.builder()
- //如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
- .setClaims(claims)
- //设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。
- .setId(UUID.randomUUID().toString())
- //iat: jwt的签发时间
- .setIssuedAt(now)
- //代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串,可以存放什么userid,roldid之类的,作为什么用户的唯一标志。
- .setSubject(subject)
- //设置签名使用的签名算法和签名使用的秘钥
- .signWith(signatureAlgorithm, key);
- if (ttlMillis >= 0) {
- long expMillis = nowMillis + ttlMillis;
- Date exp = new Date(expMillis);
- //设置过期时间
- builder.setExpiration(exp);
- }
- return builder.compact();
- }
- /**
- * Token的解密
- * @param token 加密后的token
- * @param user 用户的对象
- * @return
- */
- public static Claims parseJWT(String token, User user) {
- //签名秘钥,和生成的签名的秘钥一模一样
- String key = user.getPassword();
- //得到DefaultJwtParser
- Claims claims = Jwts.parser()
- //设置签名的秘钥
- .setSigningKey(key)
- //设置需要解析的jwt
- .parseClaimsJws(token).getBody();
- return claims;
- }
- /**
- * 校验token
- * 在这里可以使用官方的校验,我这里校验的是token中携带的密码于数据库一致的话就校验通过
- * @param token
- * @param user
- * @return
- */
- public static Boolean isVerify(String token, User user) {
- //签名秘钥,和生成的签名的秘钥一模一样
- String key = user.getPassword();
- //得到DefaultJwtParser
- Claims claims = Jwts.parser()
- //设置签名的秘钥
- .setSigningKey(key)
- //设置需要解析的jwt
- .parseClaimsJws(token).getBody();
- if (claims.get("password").equals(user.getPassword())) {
- return true;
- }
- return false;
- }
- }
第四步:编写拦截器拦截请求进行权限验证
- package com.pjb.springbootjjwt.interceptor;
- import com.auth0.jwt.JWT;
- import com.auth0.jwt.exceptions.JWTDecodeException;
- import com.pjb.springbootjjwt.jimisun.CheckToken;
- import com.pjb.springbootjjwt.jimisun.JwtUtil;
- import com.pjb.springbootjjwt.jimisun.LoginToken;
- import com.pjb.springbootjjwt.jimisun.User;
- import com.pjb.springbootjjwt.service.UserService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.method.HandlerMethod;
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.lang.reflect.Method;
- /**
- * jimisun
- */
- public class AuthenticationInterceptor implements HandlerInterceptor {
- @Autowired
- UserService userService;
- @Override
- public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
- // 从 http 请求头中取出 token
- String token = httpServletRequest.getHeader("token");
- // 如果不是映射到方法直接通过
- if (!(object instanceof HandlerMethod)) {
- return true;
- }
- HandlerMethod handlerMethod = (HandlerMethod) object;
- Method method = handlerMethod.getMethod();
- //检查是否有LoginToken注释,有则跳过认证
- if (method.isAnnotationPresent(LoginToken.class)) {
- LoginToken loginToken = method.getAnnotation(LoginToken.class);
- if (loginToken.required()) {
- return true;
- }
- }
- //检查有没有需要用户权限的注解
- if (method.isAnnotationPresent(CheckToken.class)) {
- CheckToken checkToken = method.getAnnotation(CheckToken.class);
- if (checkToken.required()) {
- // 执行认证
- if (token == null) {
- throw new RuntimeException("无token,请重新登录");
- }
- // 获取 token 中的 user id
- String userId;
- try {
- userId = JWT.decode(token).getClaim("id").asString();
- } catch (JWTDecodeException j) {
- throw new RuntimeException("访问异常!");
- }
- User user = userService.findUserById(userId);
- if (user == null) {
- throw new RuntimeException("用户不存在,请重新登录");
- }
- Boolean verify = JwtUtil.isVerify(token, user);
- if (!verify) {
- throw new RuntimeException("非法访问!");
- }
- return true;
- }
- }
- return true;
- }
- @Override
- public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
- }
- @Override
- public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
- }
- }
- package com.pjb.springbootjjwt.interceptorconfig;
- import com.pjb.springbootjjwt.interceptor.AuthenticationInterceptor;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
- import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
- @Configuration
- public class InterceptorConfig implements WebMvcConfigurer {
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(authenticationInterceptor())
- .addPathPatterns("/**"); // 拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录
- }
- @Bean
- public AuthenticationInterceptor authenticationInterceptor() {
- return new AuthenticationInterceptor();
- }
- }
第五步:在示例Controller中的实际应用
- package com.pjb.springbootjjwt.jimisun;
- import com.alibaba.fastjson.JSONObject;
- import com.pjb.springbootjjwt.annotation.PassToken;
- import com.pjb.springbootjjwt.annotation.UserLoginToken;
- import com.pjb.springbootjjwt.service.UserService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.*;
- import javax.validation.Valid;
- import java.util.UUID;
- /**
- * @Author:jimisun
- * @Description:
- * @Date:Created in 15:04 2018/8/15
- * @Modified By:
- */
- @RestController
- @RequestMapping("/api")
- public class UserController {
- @Autowired
- private UserService userService;
- //登录
- @PostMapping("/login")
- @LoginToken
- public Object login(@RequestBody @Valid com.pjb.springbootjjwt.jimisun.User user) {
- JSONObject jsonObject = new JSONObject();
- com.pjb.springbootjjwt.jimisun.User userForBase = userService.findByUsername(user);
- if (userForBase == null) {
- jsonObject.put("message", "登录失败,用户不存在");
- return jsonObject;
- } else {
- if (!userForBase.getPassword().equals(user.getPassword())) {
- jsonObject.put("message", "登录失败,密码错误");
- return jsonObject;
- } else {
- String token = JwtUtil.createJWT(6000000, userForBase);
- jsonObject.put("token", token);
- jsonObject.put("user", userForBase);
- return jsonObject;
- }
- }
- }
- //查看个人信息
- @CheckToken
- @GetMapping("/getMessage")
- public String getMessage() {
- return "你已通过验证";
- }
- }
最后一步,我们现在来访问一下啊
简单的Demo程序就到这里了,当然还有很多东西没有考虑到,比如jwt在集群环境下的应用等一些问题留到下回探讨啦~
Jwt在Java项目中的简单实际应用的更多相关文章
- java项目中ehcache缓存最简单用法
java项目中ehcache缓存最简单用法: 1.下载ehcache-core-2.4.3.jar复制到项目的lib目录下 2.新建ehcache.xml文件,放置在项目src目录下的resour ...
- JAVA项目中公布WebService服务——简单实例
1.在Java项目中公布一个WebService服务: 怎样公布? --JDK1.6中JAX-WS规范定义了怎样公布一个WebService服务. (1)用jdk1.6.0_21以后的版本号公布. ( ...
- 在Java项目中整合Scala
Scala是一个运行在Java JVM上的面向对象的语言.它支持函数编程,在语法上比Java更加灵活,同时通过Akka库,Scala支持强大的基于Actor的多线程编程.具有这些优势,使得我最近很想在 ...
- ckeditor编辑器在java项目中配置
一.基本使用: 1.所需文件架包 A. Ckeditor基本文件包,比如:ckeditor_3.6.2.zip 下载地址:http://ckeditor.com/download 2.配置使用 A.将 ...
- redis在java项目中的使用
在上一篇文章中已经讲了redis的spring配置,这篇将会描述redis在java项目中的使用. redis存储形式都是key-value(键值对),按照存储的内容分为两种,一种是存简单数据,即数字 ...
- Redis学习笔记之二 :在Java项目中使用Redis
成功配置redis之后,便来学习使用redis.首先了解下redis的数据类型. Redis的数据类型 Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set( ...
- JAVA项目中常用的异常处理情况总结
JAVA项目中常用的异常知识点总结 1. java.lang.nullpointerexception这个异常大家肯定都经常遇到,异常的解释是"程序遇上了空指针",简单地说就是调用 ...
- Ant在Java项目中的使用(一眼就看会)
参考:http://www.cnblogs.com/zhengqiang/p/5557155.html Ant是跨平台的构建工具,它可以实现项目的自动构建和部署等功能.在本文中,主要让读者熟悉怎样将A ...
- UCenter在JAVA项目中实现的单点登录应用实例
Comsenz(康盛)的UCenter当前在国内的单点登录领域占据绝对份额,其完整的产品线令UCenter成为了账号集成方面事实上的标准. 基于UCenter,可以将Comsenz旗下的Discuz! ...
随机推荐
- atitit。解决 No suitable Log constructor。。NoClassDefFoundError: org/apache/log4j/Category 找不到类的
atitit.解决 No suitable Log constructor..NoClassDefFoundError: org/apache/log4j/Category 找不到类的 1. 深的层次 ...
- Struts2使用OGNL遍历各种map总结
一.Action中的代码:MapAction.java package com.zx.demo.action; import java.util.ArrayList; import java.ut ...
- php chr() ord()中文截取乱码问题解决方法
今天看到chr() ord()中文截取乱码问题这个例子,觉得相当的不错,拿出来和大家分享下,有兴趣的朋友可以去试下,看看怎么样. 代码如下: <?php $lenth = ; $str = &q ...
- 2、Reactive Extensions for .NET(译)
实验3-引入 .net 中的 events 到 Rx 目标:前面实验中的使用各种工厂构造方法创建一个 可观察序列是一个部分.把 .net 中现有的异步数据源进行关联 是更重要的事情.在这次实验中我们将 ...
- 使用ReaderWriterLock类实现多用户读/单用户写同步
使用ReaderWriterLock类实现多用户读/单用户写同步[1] 2015-03-12 应用程序在访问资源时是进行读操作,写操作相对较少.为解决这一问题,C#提供了System.Threadin ...
- 跟着百度学习php之ThinkPHP的运行流程-2
Thinkphp为了提高编译的效率,第一次运行的时候thinkphp会把文件全部编译到temp目录下的~runtime.php文件,在第二次运行的时候会直接读取这个文件.所以我们在线下自己写代码测试的 ...
- HDU 2110 Crisis of HDU
Crisis of HDU Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- Java,Mysql-根据一个给定经纬度的点,进行附近500米地点查询–合理利用算法
Java,Mysql-根据一个给定经纬度的点,进行附近500米地点查询–合理利用算法 LBS 球面距离公式 http://wiki.myoa.info/zh-blog:20 Java,Mysql- ...
- 关于Unity的C#基础学习(五)
一.get/set访问器 class Person{ int my_age; //默认私有权限 int sex; //属性,类似于函数,但是又不是函数的东西 public int age{ get{ ...
- iBATIS SQL Maps
让我们重回到车辆管理系统和张三的故事中. 在 iBATIS SQL Maps 的世界里也存在 one-to-many.many-to-one 的关系,想必你已经对这些概念驾轻就熟了.好!还是每个 Pe ...