17 changed files with 203 additions and 167 deletions
-
6.idea/vcs.xml
-
1.idea/webContexts.xml
-
22pom.xml
-
71src/main/java/cn/star/controller/UsersController.java
-
5src/main/java/cn/star/dao/UsersDao.java
-
12src/main/java/cn/star/domian/Users.java
-
96src/main/java/cn/star/interceptor/TokenInterceptor.java
-
102src/main/java/cn/star/util/JwtUtil.java
-
13src/main/resources/spring-mvc.xml
-
0src/main/webapp/WEB-INF/jsp/Users.jsp
-
0src/main/webapp/WEB-INF/jsp/falselogin.jsp
-
3src/main/webapp/WEB-INF/jsp/index.jsp
-
0src/main/webapp/WEB-INF/jsp/success.jsp
-
0src/main/webapp/WEB-INF/jsp/successlogin.jsp
-
2src/main/webapp/WEB-INF/web.xml
-
0src/main/webapp/images
-
33src/main/webapp/static/css/styles.css
@ -0,0 +1,6 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<project version="4"> |
||||
|
<component name="VcsDirectoryMappings"> |
||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" /> |
||||
|
</component> |
||||
|
</project> |
||||
@ -1,91 +1,47 @@ |
|||||
/*package cn.star.interceptor; |
|
||||
|
package cn.star.interceptor; |
||||
|
|
||||
import cn.star.common.ApiResponse; |
|
||||
import cn.star.util.JwtUtil; |
import cn.star.util.JwtUtil; |
||||
import com.alibaba.fastjson.JSONObject; |
|
||||
import org.springframework.web.method.HandlerMethod; |
|
||||
|
import io.jsonwebtoken.Claims; |
||||
import org.springframework.web.servlet.HandlerInterceptor; |
import org.springframework.web.servlet.HandlerInterceptor; |
||||
import org.springframework.web.servlet.ModelAndView; |
|
||||
|
|
||||
import javax.servlet.http.Cookie; |
|
||||
import javax.servlet.http.HttpServletRequest; |
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.IOException; |
|
||||
import java.io.PrintWriter; |
import java.io.PrintWriter; |
||||
import java.util.HashMap; |
|
||||
import java.util.Map; |
|
||||
|
|
||||
public class TokenInterceptor implements HandlerInterceptor { |
public class TokenInterceptor implements HandlerInterceptor { |
||||
|
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { |
|
||||
|
|
||||
// 只处理HandlerMethod类型的处理器(排除静态资源等) |
|
||||
if (!(handler instanceof HandlerMethod)) { |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
System.out.println("执行方法之前执行这步操作"); |
|
||||
response.setCharacterEncoding("utf-8"); |
|
||||
|
|
||||
Cookie cookie = getCookieByName(request,"COOKIE_NAME"); |
|
||||
|
@Override |
||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { |
||||
|
//获取请求头中的token |
||||
|
|
||||
if(null != cookie) { |
|
||||
boolean result = JwtUtil.verify(cookie.getValue()); |
|
||||
if(!result) { |
|
||||
response.sendRedirect(request.getContextPath() + "/login"); |
|
||||
return false; |
|
||||
} |
|
||||
return true; |
|
||||
} |
|
||||
else { |
|
||||
response.sendRedirect(request.getContextPath() + "/login"); |
|
||||
|
String token = request.getHeader("Authorization"); |
||||
|
|
||||
|
//验证token格式 |
||||
|
if(token == null || !token.startsWith("Bearer")) { |
||||
|
returnError(response,"请先登录"); |
||||
return false; |
return false; |
||||
} |
} |
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) |
|
||||
throws Exception { |
|
||||
} |
|
||||
|
token = token.substring(7); |
||||
|
|
||||
@Override |
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {} |
|
||||
|
|
||||
//根据名字获取cookie |
|
||||
public static Cookie getCookieByName(HttpServletRequest request , String name) { |
|
||||
Map<String,Cookie> cookieMap = ReadCookieMap(request); |
|
||||
if (cookieMap.containsKey(name)) { |
|
||||
Cookie cookie = cookieMap.get(name); |
|
||||
return cookie; |
|
||||
} |
|
||||
else { |
|
||||
return null; |
|
||||
|
//验证token有效性 |
||||
|
if (!JwtUtil.isTokenValid(token)) { |
||||
|
returnError(response,"登录已过期,请重新登录"); |
||||
|
return false; |
||||
} |
} |
||||
} |
|
||||
|
|
||||
private static Map<String,Cookie> ReadCookieMap(HttpServletRequest request) { |
|
||||
Map<String,Cookie> cookieMap = new HashMap<String,Cookie>(); |
|
||||
Cookie[] cookies = request.getCookies(); |
|
||||
if (cookies != null) { |
|
||||
for (Cookie cookie : cookies) { |
|
||||
cookieMap.put(cookie.getName(), cookie); |
|
||||
} |
|
||||
} |
|
||||
return cookieMap; |
|
||||
|
//解析token获取角色,存入request继续使用 |
||||
|
Claims claims = JwtUtil.parseToken(token); |
||||
|
request.setAttribute("userId",claims.get("userId",Long.class)); |
||||
|
request.setAttribute("role",claims.get("role",Long.class)); |
||||
|
return true; |
||||
} |
} |
||||
|
|
||||
private void responseMessage(HttpServletRequest request, HttpServletResponse response, PrintWriter out, ApiResponse apiResponse) |
|
||||
throws IOException |
|
||||
{ |
|
||||
response.setContentType("text/html;charset=utf-8"); |
|
||||
out.print(JSONObject.toJSONString(apiResponse));//这个ApiResponse需要创建一个类然后调用 |
|
||||
|
//返回错误信息 |
||||
|
private void returnError(HttpServletResponse response, String message) throws Exception { |
||||
|
response.setContentType("text/html;charset=UTF-8"); |
||||
|
PrintWriter out = response.getWriter(); |
||||
|
out.write("<script>alert('" + message + "'); window.location.href='/login.html';</script>"); |
||||
out.flush(); |
out.flush(); |
||||
out.close(); |
out.close(); |
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
}*/ |
|
||||
|
} |
||||
|
} |
||||
@ -1,79 +1,49 @@ |
|||||
package cn.star.util; |
package cn.star.util; |
||||
|
|
||||
import com.auth0.jwt.JWT; |
|
||||
import com.auth0.jwt.JWTVerifier; |
|
||||
import com.auth0.jwt.algorithms.Algorithm; |
|
||||
import com.auth0.jwt.interfaces.DecodedJWT; |
|
||||
|
|
||||
import java.io.UnsupportedEncodingException; |
|
||||
|
import io.jsonwebtoken.Claims; |
||||
|
import io.jsonwebtoken.Jwts; |
||||
|
import io.jsonwebtoken.SignatureAlgorithm; |
||||
|
import io.jsonwebtoken.security.Keys; |
||||
|
import javax.crypto.SecretKey; |
||||
import java.util.Date; |
import java.util.Date; |
||||
import java.util.HashMap; |
|
||||
import java.util.Map; |
|
||||
|
|
||||
import static java.lang.System.currentTimeMillis; |
|
||||
|
|
||||
public class JwtUtil { |
public class JwtUtil { |
||||
|
//密钥-实际项目应该存在配置文件(?怎么弄 |
||||
|
private static final SecretKey SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256); |
||||
|
//Token 有效时间 |
||||
|
private static final long EXPIRATION_TIME = 2 * 60 * 60 * 1000; |
||||
|
|
||||
|
//生成token |
||||
|
public static String generateToken(Long userId,String role) { |
||||
|
|
||||
|
Date now = new Date(); |
||||
|
Date expiration = new Date(now.getTime() + EXPIRATION_TIME); |
||||
|
|
||||
|
return Jwts.builder().claim("usersId",userId) |
||||
|
.claim("role",role) |
||||
|
.setIssuedAt(now) |
||||
|
.setExpiration(expiration) |
||||
|
.signWith(SECRET_KEY) |
||||
|
.compact(); |
||||
|
} |
||||
|
|
||||
private static final long EXPIRE_TIME = 24 * 60 * 60 * 1000; //expire-到期时间 |
|
||||
|
|
||||
// token私匙 |
|
||||
private static final String TOKEN_SECRET = "f26e587c28064d0e855e72c0a6a0e618";//只是模拟自己设置的? |
|
||||
|
|
||||
//校验token是否正确 |
|
||||
public static boolean verify(String token) { |
|
||||
try { |
|
||||
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET); |
|
||||
JWTVerifier verifier = JWT.require(algorithm).build(); |
|
||||
DecodedJWT jwt = verifier.verify(token); |
|
||||
return true; |
|
||||
} catch (Exception e) { |
|
||||
return false; |
|
||||
} |
|
||||
} |
|
||||
|
// 解析Token获取信息 |
||||
|
|
||||
//return token包含的用户名 |
|
||||
public static String getUsername(String token) { |
|
||||
try { |
|
||||
DecodedJWT jwt = JWT.decode(token); |
|
||||
return jwt.getClaim("username").asString(); |
|
||||
} catch (Exception e) { |
|
||||
return null; |
|
||||
} |
|
||||
|
public static Claims parseToken(String token) { |
||||
|
return Jwts.parserBuilder() |
||||
|
.setSigningKey(SECRET_KEY) |
||||
|
.build() |
||||
|
.parseClaimsJws(token) |
||||
|
.getBody(); |
||||
} |
} |
||||
|
|
||||
//获取登录用户id |
|
||||
public static String getUserId(String token) { |
|
||||
|
//解析token是否有效 |
||||
|
public static boolean isTokenValid(String token) { |
||||
try { |
try { |
||||
DecodedJWT jwt = JWT.decode(token); |
|
||||
return jwt.getClaim("userId").asString(); |
|
||||
} catch (Exception e) { |
|
||||
return null; |
|
||||
|
Claims claims = parseToken(token); |
||||
|
return !claims.getExpiration().before(new Date()); |
||||
|
}catch (Exception e) { |
||||
|
return false;//无效或过期 |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
//生成签名,15min后过期 |
|
||||
public static String sign(String username,String userId) { |
|
||||
// 过期时间 |
|
||||
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME); |
|
||||
// 私钥及加密算法 |
|
||||
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET); |
|
||||
// 设置头部信息 |
|
||||
Map<String, Object> header = new HashMap<>(2); |
|
||||
header.put("typ", "JWT"); |
|
||||
header.put("alg", "HS256"); |
|
||||
// 附带username,userId信息,生成签名 |
|
||||
return JWT.create() |
|
||||
.withHeader(header) |
|
||||
.withClaim("loginName", username) |
|
||||
.withClaim("userId",userId) |
|
||||
.withExpiresAt(date) |
|
||||
.sign(algorithm); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
} |
} |
||||
|
|
||||
@ -1,9 +1,10 @@ |
|||||
|
<%@ page contentType="text/html;charset=UTF-8" language="java" %> |
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> |
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> |
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> |
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> |
||||
<html> |
<html> |
||||
<head> |
<head> |
||||
<title>主界面</title> |
<title>主界面</title> |
||||
<link rel="stylesheet" href="static/css/styles.css"> |
|
||||
|
<link rel="stylesheet" href="../static/css/styles.css"> |
||||
<style> |
<style> |
||||
.my-class { |
.my-class { |
||||
text-align: center; |
text-align: center; |
||||
@ -1,7 +1,30 @@ |
|||||
a { |
|
||||
color: #f80d43; |
|
||||
} |
|
||||
|
|
||||
.center-text { |
|
||||
|
.my-class { |
||||
text-align: center; |
text-align: center; |
||||
} |
} |
||||
|
/* 新增样式:登录表单容器 */ |
||||
|
.login-container { |
||||
|
position: relative; /* 相对定位,用于子元素绝对定位 */ |
||||
|
width: 300px; /* 固定宽度 */ |
||||
|
margin: 20px auto; /* 居中显示 */ |
||||
|
padding: 20px; |
||||
|
border: 1px solid #eee; /* 轻微边框 */ |
||||
|
} |
||||
|
/* 按钮容器样式 */ |
||||
|
.button-group { |
||||
|
display: flex; /* 弹性布局 */ |
||||
|
justify-content: space-between; /* 两端对齐 */ |
||||
|
margin-top: 15px; /* 与上方内容间距 */ |
||||
|
} |
||||
|
/* 基础按钮样式 */ |
||||
|
.base-btn { |
||||
|
padding: 6px 12px; |
||||
|
border: 1px solid #ccc; |
||||
|
background-color: #f5f5f5; |
||||
|
cursor: pointer; /* 鼠标悬停显示手型 */ |
||||
|
text-decoration: none; /* 去除链接下划线 */ |
||||
|
color: #333; /* 文字颜色 */ |
||||
|
font-size: 14px; |
||||
|
} |
||||
|
.base-btn:hover { |
||||
|
background-color: #e0e0e0; /* 悬停效果 */ |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue