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