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

JWT ajax java spingmvc 简洁教程的更多相关文章

  1. 转:精心挑选的12款优秀 jQuery Ajax 分页插件和教程

    在这篇文章中,我为大家收集了12个基于 jQuery 框架的 Ajax 分页插件,这些插件都提供了详细的使用教程和演示.Ajax 技术的出现使得 Web 项目的用户体验有了极大的提高,如今借助优秀的  ...

  2. Shiro+JWT+Spring Boot Restful简易教程

    序言 我也是半路出家的人,如果大家有什么好的意见或批评,请务必issue下. 项目地址:https://github.com/Smith-Cruise/Spring-Boot-Shiro . 如果想要 ...

  3. Java NIO系列教程(三) Channel之Socket通道

    目录: <Java NIO系列教程(二) Channel> <Java NIO系列教程(三) Channel之Socket通道> 在<Java NIO系列教程(二) Ch ...

  4. 12款优秀 jQuery Ajax 分页插件和教程

    12款优秀 jQuery Ajax 分页插件和教程 在这篇文章中,我为大家收集了12个基于 jQuery 框架的 Ajax 分页插件,这些插件都提供了详细的使用教程和演示.Ajax 技术的出现使得 W ...

  5. Java log4j详细教程

    Java log4j详细教程 http://www.jb51.net/article/74475.htm

  6. [转] java书籍(给Java程序猿们推荐一些值得一看的好书 + 7本免费的Java电子书和教程 )

    7本免费的Java电子书和教程 1. Thinking in Java (Third Edition) 本书的作者是Bruce Eckel,它一直都是Java最畅销的免费电子书.这本书可以帮助你系统的 ...

  7. 学习笔记之Java程序设计实用教程

    Java程序设计实用教程 by 朱战立 & 沈伟 学习笔记之JAVA多线程(http://www.cnblogs.com/pegasus923/p/3995855.html) 国庆休假前学习了 ...

  8. End-to-End Tracing of Ajax/Java Applications Using DTrace

    End-to-End Tracing of Ajax/Java Applications Using DTrace         By Amit Hurvitz, July 2007     Aja ...

  9. 阿里 Java 手册系列教程:为啥强制子类、父类变量名不同?

    摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 目录 父子类变量名相同会咋样? 为啥强制子类.父类变量名不同? ...

随机推荐

  1. openERP笔记 自定义模块开发

    ##需求描述 输入和查询课程,把信息储存到课程对象里 课程包含以下信息:名称,价格,天数,开始日期,教师,学员 每个课程可以有多个学员,要记录学员的姓名.电话.电子邮件 课程可以添加教材和作业等文档附 ...

  2. android studio/Intellij IDEA(MAC OSX)中android模拟器无法启动的一种原因

    翻了stackoverflow上好多方式,各种重装重启清理缓存,都没有效果. 后来发现,用IDEA创建的模拟器的路径是 /Users/xirtam/.android/avd 而IDE使用的路径是 AN ...

  3. windows7,python3使用time.strftime()函数报ValueError: embedded null byte

    windows7环境下,执行代码报ValueError: embedded null byte时,在原代码前面加一行代码:locale.setlocale(locale.LC_ALL,'en')即可解 ...

  4. Vsftp搭建 for centos7

    [root@hys ~]# uname -a Linux hys 3.10.0-693.el7.x86_64 #1 SMP Tue Aug 22 21:09:27 UTC 2017 x86_64 x8 ...

  5. File 文件

    1 File 概述 文件:file目录:directory路径:path File类静态成员变量: pathSeparator:与系统有关的路径分隔符,为了方便,它被表示为一个字符串separator ...

  6. scrapy学习---管道

    使用管道必须实现process_item() 方法 process_item(self, item, spider) 次方法实现数据的过滤处理等操作 open_spider(self, spider) ...

  7. 【UML】NO.55.EBook.8.UML.3.001-【UML和模式应用 第3版】

    1.0.0 Summary Tittle:[UML]NO.54.EBook.8.UML.3.001-[UML和模式应用 第3版] Style:DesignPattern Series:DesignPa ...

  8. Python Pyinstaller打包含pandas库的py文件遇到的坑

    今天的主角依然是pyinstaller打包工具,为了让pyinstaller打包后exe文件不至过大,我们的py脚本文件引用库时尽可能只引用需要的部分,不要引用整个库,多使用“from *** imp ...

  9. Ch03 数组相关操作 - 练习

    1. 编写一段代码,将a设置为一个n个随机数的数组,要求随机数介于0(包含)和n(不包含)之间. //import java.lang.Math def getArray(n:Int)={   val ...

  10. 九、使用多线程——NSThread,GCD和NSOperation

    概述 早上起床,你先打开洗衣机,然后用热水把泡面泡上,接着打开电脑开启一天的码农生活.其中“洗衣服”.“泡泡面”和“码代码”3个任务(线程)同时进行,这就是多线程.网上有许多关于多线程的经典解释,此处 ...