JWT ajax java spingmvc 简洁教程

1、添加依赖

  

        <dependency>
              <groupId>io.jsonwebtoken</groupId>
              <artifactId>jjwt</artifactId>
              <version>0.6.0</version>
        </dependency>
        <dependency>
            <groupId>com.thetransactioncompany</groupId>
            <artifactId>cors-filter</artifactId>
            <version>2.5</version>
        </dependency>
         <dependency>
            <groupId>com.thetransactioncompany</groupId>
            <artifactId>java-property-utils</artifactId>
            <version>1.9.1</version>
        </dependency>

2、登录 及登录后获取菜单信息

package com.fescotech.national.common.web.jwt;

import io.jsonwebtoken.Claims;

import java.io.IOException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.fescotech.apps.national.manager.web.api.base.IBaseUserApi;
import com.fescotech.apps.national.manager.web.dto.basic.user.BaseUser;
import com.fescotech.national.common.web.dto.Menu;
import com.fescotech.national.common.web.dto.Res;
import com.fescotech.national.common.web.menu.IMenuProvider;



@Controller
public class JWTLoginController {
    @Autowired
    private IMenuProvider menuProvider;
    @Autowired
    private IBaseUserApi iBaseUserApi;

    /**
     * 登录
     */
    @ResponseBody
    @RequestMapping(value = "/jwt/login", method = RequestMethod.POST)
    public Res login(String username, String password)throws IOException {       
        //登录成功后,查询用户信息
        BaseUser buS = new BaseUser();
        buS.setUserName(username);
        BaseUser user = iBaseUserApi.queryUserByLoginName(buS);
        //账号不存在或密码错误
        if(user == null || !password.equals(user.getUserPwd())) {
           return Res.error("0", "账号或密码不正确");
        }
        //账号不存在或密码错误
        if(user.getUserType()!=3) {
           return Res.error("0", "非超级管理员不可登录后台");
        }
        //登录成功返回 客户端 token
        String userToken = TokenUtil.getJWTString(user);
        LoginOkData ld = new LoginOkData();
        ld.setToken(userToken);
        return Res.ok("1", "登录成功", ld, 1);
    }
    /**
     * 加载用户权限菜单
     *
     */
    @ResponseBody
    @RequestMapping(value = "/jwt/getMenu", method = RequestMethod.POST)
    public Res getMenu(String token){
        //接收客户端token 进行验证
        Claims claims = TokenUtil.isValid(token, TokenUtil.key);
        if(null == claims){
           System.out.println("token 验证失败!");
           return Res.error("-1", "token失效");
        }
        //验证通过 获取用户信息
        String userId = (String)claims.get("userId");
        List<Menu> menuList = menuProvider.getUserMenu(userId, null);
        return Res.ok("1", "菜单请求成功", menuList, 1);
       
    }
}

3、生成及验证 token 

package com.fescotech.national.common.web.jwt;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import com.fescotech.apps.national.manager.web.dto.basic.user.BaseUser;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

public class TokenUtil {
    public static String key = "fescoTecth";
    /**
     * 生成token 并返回
     *
     */
    public static String getJWTString(BaseUser user){
        Map<String,Object> claims = new  HashMap<String,Object>();
        claims.put("userName", user.getUserName());
        claims.put("userId", user.getUserId());
        Date expires = new Date();
        Calendar c = Calendar.getInstance();
        c.add(Calendar.SECOND, 30);
        expires = c.getTime();
        SignatureAlgorithm signatureAlgorithm =SignatureAlgorithm.HS256;
        String jwtString = Jwts.builder()
                .setIssuer("Jersey-Security-Basic")
                .setSubject(user.getUserName())
                .setAudience("user")
                .setExpiration(expires)
                .setClaims(claims)
                .setIssuedAt(new Date())
                .setId(user.getUserId())
                .signWith(signatureAlgorithm,key)
                .compact();
        return jwtString;
    }
    
    /**
     * 验证token 是否有效
     *
     */
    public static Claims isValid(String token, String key) {
        try {
            Claims claims = (Claims)Jwts.parser().setSigningKey(key).parseClaimsJws(token.trim()).getBody();
            return claims;
        } catch (Exception e) {
            return null;
        }
    }
}

4、拦截器 添加允许跨域访问

  

package com.fescotech.national.common.web.filter;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.filter.OncePerRequestFilter;
/**
 * 拦截器,允许跨域访问
 * @author feiye
 *
 */
public class CorsFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        response.addHeader("Access-Control-Allow-Origin", "*");      //为安全起见,可配置允许访问的请求方地址。这里配置成*号,是允许所有访问。
        response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");        //为安全起见,也可配置成只允许POST请求
        response.addHeader("Access-Control-Allow-Headers", "Content-Type,auth_token");      //这里要注意,auth_token是我自定义的请求头当中带的token,在这里必须添加,否则你永远获取不到。
        response.addHeader("Access-Control-Max-Age", "60");//30 min
        filterChain.doFilter(request, response);
    }
}

5、web.xml 添加拦截器配置

  

  <filter>
    <filter-name>cros</filter-name>
    <filter-class>com.fescotech.national.common.web.filter.CorsFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>cros</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

6、前端ajax 请求 

  

logins:方法 提交用户名密码 进行登录,登录成功后,获得 token放入全局变量
getMenu:方法,提交 token 服务器进行验证,通过后,获取对应的用户信息,根据用户信息获取对应的权限菜单信息并返回,完成一次数据请求。
登录成功后,每次请求都要带上 token 服务器验证通过后,方可接收请求,否则不处理客户端请求

  

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="js/jquery.min.js"></script>
 <style>
 #mains{width:100%}
     #imgCode {width: 100px; border:1px solid green;}
 </style>
</head>
<body>
<div id="mains">
<input type="input" id="codes" > <br/>
<img id="imgCode"  src="http://localhost:61000/nmweb/captcha.jpg"/>
<br/>
<input type="button" onclick="logins()" width="100px" value="登录">
<input type="button" onclick="getMenu()" width="100px" value="菜单">
</div>
<script type="text/javascript">
var token = "";
function logins(){
var code = $("#codes").val();
var preLocalUrl = "http:/localhost:8080/nbmweb";
var url = preLocalUrl+"/jwt/login";
    $.ajax({
         type: 'POST',
          url: url,
          data: "username=admin&password=admin&captcha="+code,
         
          success:function(msg){
              console.log(msg);
              var res = jQuery.parseJSON(msg);
              var data = res.data;
             // var ldData = jQuery.parseJSON(data);            
              token = data.token;
          },
          error:function(errors){
              console.log(errors);
          }
    })
}
function getMenu(){
    var url = "http://localhost:8080/nbmweb/jwt/getMenu";
    console.log("url-->"+url);
    console.log("token-->"+token);
    $.ajax({
         type: 'POST',
          url: url,
          data:"token="+token,
          success:function(msg){
              console.log(msg);                  
          },
          error:function(errors){
              console.log(errors);
          }
})
}
</script>
</body>
</html>

7、以上demo 仅做测试,没有理论讲解比较随心,实际使用中,按需优化。

  关于,文件上传,获取验证码,token 的刷新和注销,请待下回分解

  推荐参考:https://bbs.csdn.net/topics/392006333

原文地址:https://www.cnblogs.com/feiye512/p/8717691.html