Jwt示例

Posted by zjh on August 27, 2020

jwt前端axios示例,vue+element-ui

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <!-- import CSS -->
  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
	<style type="text/css">
	.div_space{
		padding-top:20px;
		margin-bottom:20px;
	}
	</style>
</head>
<body>
  <div id="app">
  
  
	
	<div class="div_space" style="width:20%;margin:0 auto;margin-top:100px;max-length:200px;">
	<el-col ><el-input clearable v-model="account.username" placeholder="请输入账号"></el-input></el-col>
	</div>
	
	 <div class="div_space" style="clear:both;width:20%;margin:20px auto;max-length:200px;">
	<el-col ><el-input clearable placeholder="请输入密码" v-model="account.password" show-password></el-input></el-col>
	</div>
	
	<div class="div_space" style="clear:both;text-align:center">
	<el-button type="primary" @click="sign()">登录</el-button>
	<el-button type="warning" @click="verify()">验证</el-button>
	
	</div>
  </div>
</body>
  <!-- import Vue before Element -->
  <script src="https://cdn.jsdelivr.net/npm/vue"></script>
  <!-- import JavaScript -->
  <script crossorigin="anonymous" integrity="sha384-WbhdtWslh0AUD1Dhf8OExUvvjZ/VN6o2HHMsYlDXb6uf3IweMH13dGL4V/KgDc7y" src="https://lib.baomitu.com/element-ui/2.13.2/index.js"></script>
  
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <script src="https://cdn.bootcdn.net/ajax/libs/js-cookie/2.2.1/js.cookie.js"></script>
  <script>
    new Vue({
      el: '#    app',
      data: function() {
        return { 
		visible: false,
		url:"http://127.0.0.1:8601",
		auth:{
			accessToken:"",
			refreshToken:""
		},
		account:{
			username:"",
			password:""
		}
		
      }
	  },methods:{
			sign(){
				 axios({
					url:this.url+"/login",
					method: 'POST',
					data:{username:this.account.username,password:this.account.password}
					
				 })
				   .then(response =>{
				   console.log(response)
					
					 if(response.data.code==0)
				  this.$message.success("登录成功!,分发token")
				 this.auth.accessToken =  response.data.data.accessToken
				 this.auth.refreshToken = response.data.data.refreshToken
				 
				 this.setCookie("accessToken",this.auth.accessToken)
				 this.setCookie("refreshToken",this.auth.refreshToken)
				 console.log(this.getCookie("accessToken"),"------------------")
				 console.log(response.data)
					
				  })
				   .catch((error) =>{ 
				  console.log(error)
				   this.$message.error(error.response.data.msg+":"+error.response.data.data)
				 })
				 
				
			},
			verify(){
				axios({
					url:this.url+"/status",
					headers: {
						'token': this.auth.accessToken
					}
				}).then(response =>{
				   console.log(response.data)
				   if(response.data.code==0)
				   this.$message.success("权限验证通过")
				   else{
				    this.refreshAuth(this.auth.accessToken)
				   }
				  })
				   .catch((error) =>{
					this.$message.error(error)
				 })
			},refreshAuth(accessToken){
			
				axios({
					url:this.url+"/auth",
					headers: {
						'accessToken': accessToken,
						'refreshToken': this.auth.refreshToken
					}

				}).then(response =>{
				   console.log(response.data)
				   if(response.data.code==0){
					this.$message.success("refreshToken success!")
					this.auth.accessToken =  response.data.data.accessToken
				  }
				   else{
				    this.$message.error(response.data.msg)
				   }
				  })
				   .catch((error) =>{
					this.$message.error(error)
				 })
			},setCookie(key,value){
			 	return Cookies.set(key,value);
			},getCookie(key){
				return Cookies.get(key);
			},getUrlPara(name){
			
			var reg = new RegExp("(^|\\?|&)"+ name +"=([^&]*)(\\s|&|$)", "i");   

			return reg.test(location.href+"?name=1") ? unescape(RegExp.$2.replace(/\+/g, " ")) : ""; 
		
			//***************
	  }
	  },
	  created:function(){
		var url = "http://localhost:8080/1?name=啊啊啊"
		console.log(url.toString().substr(url.indexOf("?")+1).split("=")[1])
	}
    })
	
	
  </script>
</html>


jwt后端示例:springboot

依赖

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 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.3.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cn.zjh.spring</groupId>
    <artifactId>server-auto</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>server-auto</name>
    <description>shrio+jwt in springboot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.8.3</version>
        </dependency>

        <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>


        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.1.5.Final</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.10</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.5</version>
        </dependency>



    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>


controller:

AuthController.java

import cn.zjh.spring.serverauth.auth.dto.AutoDTO;
import cn.zjh.spring.serverauth.auth.dto.TokenDTO;
import cn.zjh.spring.serverauth.auth.utils.JwtUtil;
import com.baomidou.mybatisplus.extension.api.R;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.text.SimpleDateFormat;
import java.util.Date;


@RestController
@CrossOrigin
@Slf4j
public class AuthController {
    private final static Logger logger = LoggerFactory.getLogger("accountSignServiceLog");
    @PostMapping("/login")
    public ResponseEntity<R<TokenDTO>> login(@Valid @RequestBody AutoDTO autoDTO, HttpServletRequest request) {
        //登录成功
        String accessToken,refreshToken;
        TokenDTO tokenDTO=null;
        try {
            //accessToken为2分钟
            accessToken = JwtUtil.sign(autoDTO.getUsername() + ""+autoDTO.getPassword(),1000*5);
            //refreshToken过期时间为七天
            refreshToken = JwtUtil.sign(autoDTO.getUsername() + ""+autoDTO.getPassword(),1000*60*60*24*7);
            //builder模式重构
            tokenDTO=TokenDTO.builder().accessToken(accessToken).refreshToken(refreshToken).build();
        } catch (Exception e) {
           log.error("api in /login has exception about"+e);
        }
        //异步存储登陆日志
        logger.info("\r\n登录日志 \t\t-->"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"\t\t-->ip:"+request.getRemoteHost()+"\t\t-->"+autoDTO.getUsername()+"已登入");
        return ResponseEntity.status(HttpStatus.OK).body(R.ok(tokenDTO));
    }
    @GetMapping("/status")
    public R<Boolean> status( @RequestHeader String token){
        boolean verify = JwtUtil.verify(token);
        return verify?R.ok(true):R.failed("验证失败");
    }

    @GetMapping("/auth")
    public R<TokenDTO> refreshToken(     @RequestHeader String accessToken,@RequestHeader String refreshToken){
        if(JwtUtil.verify(refreshToken)){
        String accessTokenUsername;
       try {

           accessTokenUsername = JwtUtil.getUsername(accessToken);
       }catch (Exception ex){
           //accessToken无效
           return R.failed("认证失败,token格式错误");
       }
            //对比accessToken 和 refreshToken的用户信息
            if(accessToken.equals(JwtUtil.getUsername(refreshToken))){
            accessToken = JwtUtil.sign(accessTokenUsername, 1000 * 5);
        TokenDTO tokenDTO = new TokenDTO(accessToken,refreshToken);
        return R.ok(tokenDTO);
            }else{
                return R.failed("非法参数!(accessInfo != refreshInfo)");
            }
        }else{
            //refreshToken 过期
            return R.failed("认证失败,请重新登录");
        }
    }

    @GetMapping("/getCookie")
    public void getCookie(HttpServletRequest request){
        Cookie[] cookies =  request.getCookies();
        if(cookies != null){
            for(Cookie cookie : cookies){
                    System.out.println(cookie.getValue());
            }
        }

    }

}

DTO:

AuthDTO.java

import lombok.Builder;
import lombok.Data;

import javax.validation.constraints.NotBlank;

@Data

public class AutoDTO {
    @NotBlank(message = "用户名不能为空")
    private String username;
    @NotBlank(message = "密码不能为空")
    private String password;
    @Builder
    public AutoDTO() {
    }
    @Builder
    public AutoDTO(@NotBlank(message = "用户名不能为空") String username, @NotBlank(message = "密码不能为空") String password) {
        this.username = username;
        this.password = password;
    }
}


TokenDTO.java

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class TokenDTO {
    private String accessToken;
    private String refreshToken;

    public TokenDTO() {

    }
    public TokenDTO(String accessToken, String refreshToken) {
        this.accessToken = accessToken;
        this.refreshToken = refreshToken;
    }
}


Utils:

JwtUtil.java

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;


import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Component
public class JwtUtil {
    /**
     *  过期时长
     */
//    private static final long EXPIRE_TIME=30 *1000;

    /**
     * 私钥,使用它生成token,最好进行下加密
     */
    private static  String TOKEN_SECRET="poadh981gndo1xdobvIT!*(GEOB!({sH)SH!SH!GDadad";

    private static final String EXP = "exp";
    private static final String PAYLOAD = "payload";


    public static String sign(String useName,long exprieTime){
        try{
            Date date=new Date(System.currentTimeMillis()+exprieTime);
            //私钥及加密算法
            Algorithm algorithm=Algorithm.HMAC256(TOKEN_SECRET);
            //设置头部信息
            Map<String,Object> header=new HashMap<>();
            header.put("typ","JWT");
            header.put("alg","HS256");
            //附带username和userid信息,存储到token中,生成签名
            return JWT.create()
                    .withHeader(header)
                    //存储自己想要留存给客户端浏览器的内容
                    .withClaim("username",useName)
                    .withExpiresAt(date)
                    .sign(algorithm);


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

    //解密,传入一个加密后的token字符串和解密后的类型
    public static boolean verify(String token){

        try {
            Algorithm algorithm=Algorithm.HMAC256(TOKEN_SECRET);
            JWTVerifier verifier =JWT.require(algorithm).build();
            //此方法若token验证失败会抛错的,所以直接return true没问题
            verifier.verify(token);
            return true;
        }catch (Exception e){
            log.info("token验证失效");
            return false;
        }

    }


    /**
     * 获取token中信息 userName
     * @param token
     * @return
     */
    public static String getUsername(String token) {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("username").asString();
    }



}