Token
概述
Token 是服务端生成的一串字符串,以作为客户端进行请求的一个令牌,当第一次登录后,服务器生成一个 Token 便将此 Token 返回给客户端,以后客户端只需带上这个 Token 前来请求数据即可,无需再次带上用户名和密码。
优势
-
无状态、可扩展
- 在客户端存储的
Tokens
是无状态的,并且能够被扩展。基于这种无状态和不存储Session
信息,负载负载均衡器能够将用户信息从一个服务传到其他服务器上。tokens
自己hold
住了用户的验证信息。
- 在客户端存储的
-
Tokens
能够创建与其它程序共享权限的程序。 -
跨域
-
安全
- 请求中发送
token
而不再是发送cookie
能够防止CSRF
(跨站请求伪造)。即使在客户端使用cookie
存储token
,cookie
也仅仅是一个存储机制而不是用于认证。不将信息存储在Session
中,让我们少了对session
操作。
- 请求中发送
-
Token 设置过期时间
JWT
概述
官网:https://jwt.io/
GitHub:https://github.com/auth0/java-jwt
API:https://javadoc.io/doc/com.auth0/java-jwt/latest/index.html
JSON Web令牌(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间安全地将信息作为 JSON 对象传输。 由于此信息是经过数字签名的,因此可以被验证和信任。 可以使用秘钥(使用 HMAC 算法)或使用 RSA 或 ECDSA 的公用/专用密钥对对 JWT 进行签名。
在前后端或者服务器进行交互的过程中,通过 JSON 形式作为 Web 应用中的令牌,以完成数据传输、加密、签名等相关处理操作。
JWT 认证流程
- 首先,前端通过 Web 表单将自己的用户名和密码发送到后端的接口。这一过程一般是一个 HTTP POST 请求。建议的方式是通过 SSL 加密的传输(https协议),从而避免敏感信息被嗅探。
- 后端核对用户名和密码成功后,将用户的 id 等其他信息作为 JWT Payload (载荷),将其与头部分别进行 Base64 编码拼接后再生成一个签名,形成一个 JWT(Token)。形成的 JWT 就是一个形同 111.ZzZz.xxx 的字符串。
- 后端将 JWT 字符串作为登录成功的返回结果返回给前端。前端可以将返回的结果保存在 localStorage 或 sessionStorage 上,退出登录时前端删除保存的 JWT 即可。
- 前端在每次请求时将 JWT 放入 HTTP Header 中的 Authorization 位。(解决XSS和XSRF问题)
- 后端检查是否存在,如存在验证 JWT 的有效性。例如,检查签名是否正确;检查 Token 是否过期;检查 Token 的接收方是否是自己(可选)。
- 验证通过后后端使用 JWT 中包含的用户信息进行其他逻辑操作,返回相应结果。
JWT 的优势
- 简洁(Compact):可以通过URL,POST参数或者在HTTP header发送,因为数据量小,传输速度也很快
- 自包含(Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库
- 因为Token是以 JSON 加密的形式保存在客户端的,所以 JWT 是跨语言的,原则上任何web形式都支持。
- 不需要在服务端保存会话信息,特别适用于分布式微服务。
JWT 的组成【重点】
JWT 有3个组成部分,每个部分之间用 . 进行分隔
- Header
- Payload
- Signature
格式为
xxxxx.yyyyy.zzzzz
1、头部(header) 声明类型以及加密算法,例如 HMAC、SHA256或 RSA。
{"alg":"HS256","typ":"JWT"}
2、载荷(payload) 携带一些用户身份信息,用户id,颁发机构,颁发时间,过期时间等。用Base64进行了处理。这一段其实是明文,所以一定不要放敏感信息。例如
{"id": 200, "username": "易烊千玺"}
3、签证(signature) 签名信息,使用了自定义的盐然后加密后的结果,目的就是为了保证签名的信息没有被别人改过,这个一般是让服务器验证的。
JWT 入门
public class JwtTest {
// 通过JWT获取token
@Test
public void createToken() {
HashMap<String, Object> header = new HashMap<>();
header.put("alg", "HS256");
header.put("typ", "JWT");
Calendar expireTime = Calendar.getInstance();
expireTime.add(Calendar.MINUTE, 30);
// 创建一个Token
String token = JWT.create().
// 头部
withHeader(header).
// 载荷
withClaim("username", "易烊千玺").
withClaim("id", 1).
withExpiresAt(expireTime.getTime()).
// 签名(盐)
sign(Algorithm.HMAC256("ABC8D!EFG"));
System.out.println(token);
}
// 验证JWT的token
@Test
public void verifyToken() {
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("ABC8D!EFG")).build();
DecodedJWT verify = jwtVerifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjE4MTM4NzY0LCJ1c2VybmFtZSI6IuaYk-eDiuWNg-eOuiJ9.IhMvu1CPUVd94rPTu6HNQTGP_fBTOaJaAofD7WTDFwo");
System.out.println("token头:" + verify.getHeader());
System.out.println("token载荷:" + verify.getPayload());
System.out.println("token签名:" + verify.getSignature());
System.out.println("id:" + verify.getClaim("id").asInt());
System.out.println("username:" + verify.getClaim("username").asString());
System.out.println("过期时间:" + verify.getExpiresAt());
}
}
JWT 工具类
/**
* JWT工具类
*/
public class JwtUtils {
// token头算法
private static final String ALG = "HS256";
// token头类型
private static final String TYP = "JWT";
// token签名算法
private static final Algorithm ALGORITHM;
// token头
private static final HashMap<String, Object> HEADER = new HashMap<>();
// token签名
private static final String SIGN = "QwErTyUi";
// 静态代码块加载token头以及token签名算法
static {
HEADER.put("alg", ALG);
HEADER.put("typ", TYP);
ALGORITHM = Algorithm.HMAC256(SIGN);
}
/**
* 获取Token
*
* @param claim 载荷
* @param expireTime 过期时间,单位:分钟
* @return token
*/
public static String getToken(Map<String, Object> claim, Integer expireTime) {
// 返回创建的token
return JWT.create().
// 设置头
withHeader(HEADER).
// 设置过期时间,单位为分钟
withExpiresAt(new Date(System.currentTimeMillis() + expireTime * 1000 * 60)).
// 设置载荷
withClaim("claim", claim).
// 设置签名
sign(ALGORITHM);
}
/**
* 解析token
*
* @param token token
* @return 验证的信息
*/
public static DecodedJWT parseToken(String token) {
// 获取token
return JWT.require(ALGORITHM).build().verify(token);
}
/**
* 根据token获取载荷信息
*
* @param token token
* @return 验证的载荷
*/
public static Map<String, Object> getClaim(String token) {
// 获取token中的载荷信息
return parseToken(token).getClaim("claim").asMap();
}
/**
* 判断是否过期
*
* @param token token
* @return 是否已过期
*/
public static boolean isExpiration(String token) {
return parseToken(token).getExpiresAt().before(new Date());
}
}
测试
public class JwtUtilsTest {
@Test
public void test() {
// 准备载荷
HashMap<String, Object> map = new HashMap<>();
map.put("username", "易烊千玺");
// 获取token
String token = JwtUtils.getToken(map, 30);
System.out.println(token);
// 获取token中的载荷
Map<String, Object> claim = JwtUtils.getClaim(token);
String username = (String) claim.get("username");
System.out.println(username);
}
}
SpringMvc 整合 JWT
pom.xml
<dependencies>
<!--spring Mvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.5</version>
</dependency>
<!--Servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<!--JWT-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.14.0</version>
</dependency>
<!--Json解析-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.2</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
</dependencies>
实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String username;
private String password;
}
业务层及实现类
public interface UserService {
User login(String username, String password);
}
@Service
public class UserServiceImpl implements UserService {
@Override
public User login(String username, String password) {
if (username.equals("易烊千玺") && password.equals("123456")) {
return new User(username, password);
}
return null;
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--配置前端控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--读取springmvc配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springMvc.xml</param-value>
</init-param>
<!--启动时加载-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--配置前端控制器的访问路径-->
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录页</title>
</head>
<body>
<form>
<table align="center">
<tr>
<td>账号</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td colspan="1" align="center">
<input type="button" value="登录" οnclick="login()">
</td>
</tr>
</table>
</form>
</body>
<script src="js/jquery-1.8.3.min.js"></script>
<script type="text/javascript">
function login() {
// 序列化表单内容
var data = $("form").serialize();
// 访问后端资源
$.ajax({
type: "post",
url: "/user/login",
data: data,
success: function (resp) {
// 将token存入localStorage
localStorage.setItem("token", resp.token);
// 跳转页面
$(location).attr('href', '/index.jsp');
}
})
}
</script>
</html>
常规用法
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>主页</title>
</head>
<body>
<h1 align="center" style="color: blue">欢迎<span id="username"></span>来到主页</h1>
</body>
<script src="js/jquery-1.8.3.min.js"></script>
<script type="text/javascript">
$(function () {
// 从localStorage中获取token
var token = localStorage.getItem("token");
// 如果token为空
if (token === null) {
// 跳转回登录页面
$(location).attr('href', '/login.jsp');
}
// 访问后端接口获取资源
$.ajax({
type: "post",
url: "/user/get",
data: {"token": token},
success: function (resp) {
// 如果响应状态为200
if (resp.code === 200) {
// 获取资源
$("#username").text(resp.data.username)
}
}
})
})
</script>
</html>
controller
@Controller
@RequestMapping("user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("login")
@ResponseBody
public Map<String, Object> login(User user) {
// 准备一个Map用来返回Json类型数据
Map<String, Object> map = new HashMap<>();
map.put("code", -1);
map.put("message", "登录失败");
// 登录并获取User对象
User result = userService.login(user.getUsername(), user.getPassword());
// 如果User对象不为空说明登录成功
if (result != null) {
// 准备载荷信息
Map<String, Object> claim = new HashMap<>();
claim.put("username", result.getUsername());
// 获取token
String token = JwtUtils.getToken(claim, 30);
map.put("code", 200);
map.put("message", "登录成功");
map.put("token", token);
}
return map;
}
@PostMapping("get")
@ResponseBody
public Map<String, Object> get(String token) {
// 准备一个Map用来返回Json类型数据
Map<String, Object> map = new HashMap<>();
map.put("code", -1);
// 如果token不存在,访问被拒绝
if (token == null) {
map.put("message", "token不存在,访问被拒绝");
}
// 通过工具类获取载荷信息
try {
Map<String, Object> claim = JwtUtils.getClaim(token);
map.put("message", "允许访问");
map.put("code", 200);
map.put("data", claim);
// 抛出对应的异常
} catch (AlgorithmMismatchException e) {
map.put("message", "算法不匹配");
} catch (InvalidClaimException e) {
map.put("message", "非法载荷");
} catch (SignatureVerificationException e) {
map.put("message", "签名不匹配");
} catch (TokenExpiredException e) {
map.put("message", "token已过期");
} catch (Exception e) {
map.put("message", "token异常,访问被终止");
}
return map;
}
}
springMvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启注解扫描 -->
<context:component-scan base-package="com.fc"/>
<!-- 视图解析器对象 -->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
<!-- 开启SpringMVC框架注解的支持 -->
<mvc:annotation-driven/>
<!--放行静态资源-->
<mvc:default-servlet-handler/>
</beans>
使用拦截器
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>主页</title>
</head>
<body>
<h1 align="center" style="color: blue">欢迎<span id="username"></span>来到主页</h1>
</body>
<script src="js/jquery-1.8.3.min.js"></script>
<script type="text/javascript">
$(function () {
// 从localStorage中获取token
var token = localStorage.getItem("token");
// 如果token为空
if (token === null) {
// 跳转回登录页面
$(location).attr('href', '/login.jsp');
}
// 访问后端接口获取资源
$.ajax({
type: "get",
url: "/user/get",
async: false,
headers: {"token": token},
success: function (resp) {
// 如果响应状态为200
if (resp.code === 200) {
// 获取资源
$("#username").text(resp.data.username)
}
}
})
})
</script>
</html>
controller
@Controller
@RequestMapping("user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("login")
@ResponseBody
public Map<String, Object> login(User user) {
// 准备一个Map用来返回Json类型数据
Map<String, Object> map = new HashMap<>();
map.put("code", -1);
map.put("message", "登录失败");
// 登录并获取User对象
User result = userService.login(user.getUsername(), user.getPassword());
// 如果User对象不为空说明登录成功
if (result != null) {
// 准备载荷信息
Map<String, Object> claim = new HashMap<>();
claim.put("username", result.getUsername());
// 获取token
String token = JwtUtils.getToken(claim, 30);
map.put("code", 200);
map.put("message", "登录成功");
map.put("token", token);
}
return map;
}
@GetMapping("get")
@ResponseBody
public Map<String, Object> get(HttpServletRequest request) {
// 准备一个Map用来返回Json类型数据
Map<String, Object> map = new HashMap<>();
map.put("code", 200);
map.put("message", "请求成功");
map.put("data", request.getAttribute("claim"));
return map;
}
}
自定义 Jwt 拦截器
/**
* 自定义Jwt拦截器
*/
public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 从请求头中获取token
String token = request.getHeader("token");
Map<String, Object> map = new HashMap<>();
map.put("code", -1);
try {
// 解析token并获取载荷
Map<String, Object> claim = JwtUtils.getClaim(token);
// 设置到域对象中
request.setAttribute("claim", claim);
return true;
// 抛出对应的异常
} catch (AlgorithmMismatchException e) {
map.put("message", "算法不匹配");
} catch (InvalidClaimException e) {
map.put("message", "非法载荷");
} catch (SignatureVerificationException e) {
map.put("message", "签名不匹配");
} catch (TokenExpiredException e) {
map.put("message", "token已过期");
} catch (Exception e) {
map.put("message", "token异常,访问被终止");
}
// 获取Jackson核心处理对象
ObjectMapper objectMapper = new ObjectMapper();
// 对象转Json字符串
String json = objectMapper.writeValueAsString(map);
// 设置响应内容类型
response.setContentType("application/json; charset=UTF-8");
// 发送响应
response.getWriter().println(json);
return false;
}
}
springMvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启注解扫描 -->
<context:component-scan base-package="com.fc"/>
<!-- 视图解析器对象 -->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
<!-- 开启SpringMVC框架注解的支持 -->
<mvc:annotation-driven/>
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--拦截的路径-->
<mvc:mapping path="/**"/>
<!--不拦截的路径-->
<mvc:exclude-mapping path="/user/login"/>
<!--自定义拦截器-->
<bean class="com.fc.interceptor.JwtInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
<!--放行静态资源-->
<mvc:default-servlet-handler/>
</beans>
【扩展】自定义 JWT 并加入权限认证
1、pom.xml引入依赖
<!--json解析-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.2</version>
</dependency>
<!--Apache下的包含各种格式的简单编码器和解码器,如Base64和十六进制-->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
2、jwt工具类
/**
* 自定义jwt工具类
*/
public class JwtUtils {
/**
* 获取JWT
*
* @param claim 载荷
* @param salt 盐
* @return JWT
*/
public static String getJWT(Map<String, Object> claim, String salt) {
// 添加一个时间戳
claim.put("time", System.currentTimeMillis() + 1000 * 60 * 30);
// 未编码的头部
String decodedHeader = "{\"alg\":\"HS256\"}";
// 使用base64算法对二进制数据进行编码,获取编码后的头部
String header = Base64.getEncoder().encodeToString(decodedHeader.getBytes(StandardCharsets.UTF_8));
// 准备json解析的对象
ObjectMapper objectMapper = new ObjectMapper();
String jsonDecoded = null;
try {
// 将载荷转为json字符串
jsonDecoded = objectMapper.writeValueAsString(claim);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
// 使用base64算法对二进制数据进行编码,获取编码后的载荷
String payload = Base64.getEncoder().encodeToString(jsonDecoded.getBytes(StandardCharsets.UTF_8));
// 获取16进制的md5加密后的签名
String signature = DigestUtils.md5Hex(jsonDecoded + salt);
// 准备一个StringBuilder
StringBuilder stringBuilder = new StringBuilder();
// 将头部,载荷,签名进行拼接
StringBuilder append = stringBuilder.append(header).append(".").append(payload).append(".").append(signature);
// 类型转换获取JWT
return new String(append);
}
/**
* 解析JWT
*
* @param jwt jwt
* @param salt 盐
* @return 响应结果
*/
public static Map<String, Object> decodeJwt(String jwt, String salt) {
// 声明响应的结果,默认为false
Map<String, Object> result = new HashMap<>();
result.put("success", false);
// 拆分jwt为字符串数组
String[] jwtArr = jwt.split("\\.");
// 获取未解码的载荷
String payloadBase64 = jwtArr[1];
// 获取解码后的载荷字节数组
byte[] decode = Base64.getDecoder().decode(payloadBase64.getBytes(StandardCharsets.UTF_8));
// 获取解码后的载荷
String payload = new String(decode);
// 准备json解析对象
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> claim = null;
try {
// 将json类型的载荷解析为Map对象
claim = objectMapper.readValue(payload, new TypeReference<Map<String, Object>>() {});
// 获取载荷中的时间
Long time = (Long) claim.get("time");
// 如果大于当前时间说明jwt已失效,携带错误信息并返回
if (time < System.currentTimeMillis()) {
result.put("message", "当前jwt已失效");
return result;
}
} catch (JsonProcessingException e) {
e.printStackTrace();
}
// 载荷加上盐值
payload += salt;
// 使用md5生成签名
String sign = DigestUtils.md5Hex(payload);
// 和jwt中的签名对比
if (sign.equals(jwtArr[2])) {
// 将载荷放入响应内容中并返回
result.put("success", true);
result.put("message", "访问成功");
result.putAll(claim);
return result;
}
// 签名不相同说明jwt被篡改了,返回错误信息
result.put("message", "非法的jwt");
return result;
}
}
3、测试类
public class JwtTest {
@Test
public void test() {
// 准备一个盐值
String salt = "123456";
// 准备载荷
Map<String, Object> map = new HashMap<>();
map.put("username", "送你一朵小红花");
map.put("id", 1);
map.put("age", 21);
// 使用工具类生成jwt
String jwt = JwtUtils.getJWT(map, salt);
System.out.println(jwt);
// 使用盐值解析jwt
Map<String, Object> payload = JwtUtils.decodeJwt(jwt, salt);
// 判断是否解析成功
boolean success = (boolean) payload.get("success");
if (success) {
System.out.println(payload.get("username"));
} else {
System.out.println(payload.get("message"));
}
}
}
4、前端页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<script src="js/jquery-1.8.3.min.js"></script>
<body>
<form action="user/login" method="post">
<table align="center">
<caption><h1>测试jwt</h1></caption>
<tr>
<td>账号</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td align="center" colspan="2">
<input type="reset" value="重置">
<button type="button" onclick="login()">提交</button>
</td>
</tr>
</table>
</form>
</body>
<script type="text/javascript">
function login() {
var data = $("form").serialize();
$.ajax({
url: "user/login",
data: data,
success: function (res) {
localStorage.setItem("jwt", res.jwt);
window.location.href = "/success.html";
}
})
}
</script>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录成功页</title>
</head>
<script src="js/jquery-1.8.3.min.js"></script>
<body>
<button type="button" onclick="add()">添加</button>
<button type="button" onclick="show()">查看</button>
</body>
<script type="text/javascript">
var jwt = localStorage.getItem("jwt");
function add() {
$.ajax({
url: "user/add",
data: {"jwt": jwt},
success: function (res) {
alert(res.message);
}
})
}
function show() {
$.ajax({
url: "user/select",
data: {"jwt": jwt},
success: function (res) {
alert(res.message);
}
})
}
</script>
</html>
5、控制层
@RestController
@RequestMapping("user")
public class UserController {
@RequestMapping("login")
public Map<String, Object> login(String username, String password, HttpServletResponse response) {
Map<String, Object> map = new HashMap<>();
// 判断登录用户是否为管理员用户,如果是,添加管理员权限
if (username.equals("易烊千玺") && password.equals("123456")) {
map.put("auth", "admin");
} else {
// 不是管理员,添加普通权限
map.put("auth", "user");
}
// 将生成的jwt存入响应内容中
map.put("jwt", JwtUtils.getJWT(map, "salt"));
return map;
}
@RequestMapping("add")
public Map<String, Object> add(@RequestParam String jwt) {
// 解码jwt获取载荷
Map<String, Object> map = JwtUtils.decodeJwt(jwt, "salt");
// 获取载荷中的参数
boolean success = (boolean) map.get("success");
// 判断jwt是否解码成功
if (success) {
// 获取jwt中存储的用户权限
String auth = String.valueOf(map.get("auth"));
// 判断是否为管理员权限
if (auth.equals("admin")) {
map.put("message", "欢迎管理员进行访问");
} else {
map.put("message", "权限不够");
}
}
return map;
}
@RequestMapping("select")
public Map<String, Object> select(@RequestParam String jwt) {
// 解码jwt获取载荷
Map<String, Object> map = JwtUtils.decodeJwt(jwt, "salt");
// 获取载荷中的参数
boolean success = (boolean) map.get("success");
// 判断jwt是否解码成功
if (success) {
String auth = String.valueOf(map.get("auth"));
// 判断是否为管理员权限
if (auth.equals("admin")) {
map.put("message", "欢迎管理员访问");
} else {
map.put("message", "欢迎访问");
}
}
return map;
}
}
boolean success = (boolean) map.get("success");
// 判断jwt是否解码成功
if (success) {
// 获取jwt中存储的用户权限
String auth = String.valueOf(map.get("auth"));
// 判断是否为管理员权限
if (auth.equals("admin")) {
map.put("message", "欢迎管理员进行访问");
} else {
map.put("message", "权限不够");
}
}
return map;
}
@RequestMapping("select")
public Map<String, Object> select(@RequestParam String jwt) {
// 解码jwt获取载荷
Map<String, Object> map = JwtUtils.decodeJwt(jwt, "salt");
// 获取载荷中的参数
boolean success = (boolean) map.get("success");
// 判断jwt是否解码成功
if (success) {
String auth = String.valueOf(map.get("auth"));
// 判断是否为管理员权限
if (auth.equals("admin")) {
map.put("message", "欢迎管理员访问");
} else {
map.put("message", "欢迎访问");
}
}
return map;
}
}