主动登录后台代码
6.1 依赖
<!-- thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.7</version>
</dependency>
<!-- JWT 核心依赖 -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
<!-- Java开发 JWT的依赖jar -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
6.2 自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginRequired {
/**
* true 必须登录,验证
* false 可以不登陆,必须验证
*/
boolean loginSuccess();
}
6.3 util
public class CookieUtil {
/**
* 得到Cookie的值, 不编码
*
* @param request
* @param cookieName
* @return
*/
public static String getCookieValue(HttpServletRequest request, String cookieName) {
return getCookieValue(request, cookieName, false);
}
/**
* 得到Cookie的值,
*
* @param request
* @param cookieName
* @return
*/
public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) {
Cookie[] cookieList = request.getCookies();
if (cookieList == null || cookieName == null) {
return null;
}
String retValue = null;
try {
for (int i = 0; i < cookieList.length; i++) {
if (cookieList[i].getName().equals(cookieName)) {
if (isDecoder) {
retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8");
} else {
retValue = cookieList[i].getValue();
}
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return retValue;
}
/**
* 得到Cookie的值,
*
* @param request
* @param cookieName
* @return
*/
public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) {
Cookie[] cookieList = request.getCookies();
if (cookieList == null || cookieName == null) {
return null;
}
String retValue = null;
try {
for (int i = 0; i < cookieList.length; i++) {
if (cookieList[i].getName().equals(cookieName)) {
retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return retValue;
}
/**
* 设置Cookie的值 不设置生效时间默认浏览器关闭即失效,也不编码
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue) {
setCookie(request, response, cookieName, cookieValue, -1);
}
/**
* 设置Cookie的值 在指定时间内生效,但不编码
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue, int cookieMaxage) {
setCookie(request, response, cookieName, cookieValue, cookieMaxage, false);
}
/**
* 设置Cookie的值 不设置生效时间,但编码
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue, boolean isEncode) {
setCookie(request, response, cookieName, cookieValue, -1, isEncode);
}
/**
* 设置Cookie的值 在指定时间内生效, 编码参数
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue, int cookieMaxage, boolean isEncode) {
doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, isEncode);
}
/**
* 设置Cookie的值 在指定时间内生效, 编码参数(指定编码)
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue, int cookieMaxage, String encodeString) {
doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, encodeString);
}
/**
* 删除Cookie带cookie域名
*/
public static void deleteCookie(HttpServletRequest request, HttpServletResponse response,
String cookieName) {
doSetCookie(request, response, cookieName, "", -1, false);
}
/**
* 设置Cookie的值,并使其在指定时间内生效
*
* @param cookieMaxage cookie生效的最大秒数
*/
private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,
String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {
try {
if (cookieValue == null) {
cookieValue = "";
} else if (isEncode) {
cookieValue = URLEncoder.encode(cookieValue, "utf-8");
}
Cookie cookie = new Cookie(cookieName, cookieValue);
if (cookieMaxage > 0)
cookie.setMaxAge(cookieMaxage);
if (null != request) {// 设置域名的cookie
String domainName = getDomainName(request);
System.out.println(domainName+"++++++++++++++++++++++++");
if (!"localhost".equals(domainName)) {
cookie.setDomain(domainName);
}
}
cookie.setPath("/");
response.addCookie(cookie);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 设置Cookie的值,并使其在指定时间内生效
*
* @param cookieMaxage cookie生效的最大秒数
*/
private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,
String cookieName, String cookieValue, int cookieMaxage, String encodeString) {
try {
if (cookieValue == null) {
cookieValue = "";
} else {
cookieValue = URLEncoder.encode(cookieValue, encodeString);
}
Cookie cookie = new Cookie(cookieName, cookieValue);
if (cookieMaxage > 0)
cookie.setMaxAge(cookieMaxage);
if (null != request) {// 设置域名的cookie
String domainName = getDomainName(request);
System.out.println(domainName+"---------------");
if (!"localhost".equals(domainName)) {
//本地测试的时候不要写.实际发布时在打开
cookie.setDomain(domainName);
}
}
cookie.setPath("/");
response.addCookie(cookie);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 得到cookie的域名
*/
private static final String getDomainName(HttpServletRequest request) {
String domainName = null;
String serverName = request.getRequestURL().toString();
if (serverName == null || serverName.equals("")) {
domainName = "";
} else {
serverName = serverName.toLowerCase(); //转为小写
final int end = serverName.lastIndexOf("/");
serverName = serverName.substring(0, end);
final String[] domains = serverName.split("\\.");
int len = domains.length;
if (len > 3) {
// www.xxx.com.cn
domainName = domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];
} else if (len <= 3 && len > 1) {
// xxx.com or xxx.cn
domainName = domains[len - 2] + "." + domains[len - 1];
} else {
domainName = serverName;
}
}
if (domainName != null && domainName.indexOf(":") > 0) {
String[] ary = domainName.split("\\:");
domainName = ary[0];
}
return domainName;
}
}
/**
* JWT工具
*/
public class JWTUtils {
/**
* 自定义的
*/
//服务器的key.用于做加解密的key数据
private static final String JWT_SECRET = "test_jwt_secret";
private static final ObjectMapper objectMapper = new ObjectMapper();
private static final int JWT_ERRCODE_EXPIRE = 1005; //Token 超时
private static final int JWT_ERROR_FAIL = 1006; //验证不通过
/**
* key 加密
*/
public static SecretKey generalKey() {
try {
byte[] bytes = JWT_SECRET.getBytes("UTF-8");
SecretKey keySpec = new SecretKeySpec(bytes, 0, bytes.length, "AES");
return keySpec;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
/**
* 签发JWT,创建Token的方法
*
* @param id jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击.
* @param iss jwt签发者
* @param subject jwt所面向的用户.payload中记录的public claims.当前环境中就是用户名.
* @param ttlMillis 有效期.单位毫秒
* token是一次性的.十位用户的有效登录周期准备的一个token.用户退出或超时时,token失效.
*/
public static String creatJWT(String id, String iss, String subject, long ttlMillis) {
//创建一个加密算法
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
//获得当前时间
long time = new Date().getTime();
Date date = new Date(time);
//获得key
SecretKey secretKey = generalKey();
//创建JWT的构建器.就是使用指定的信息和加密算法,生成Token的工具.
JwtBuilder builder = Jwts.builder();
builder.setId(id);
builder.setIssuer(iss);
builder.setSubject(subject);
builder.setIssuedAt(date);
builder.signWith(signatureAlgorithm, secretKey);
if (ttlMillis > 0) {
long expMillis = time + ttlMillis;
Date date1 = new Date(expMillis);
builder.setExpiration(date1);
}
String token = builder.compact();
return token;
}
/**
* 验证JWT
*/
public static JWTResult validateJWT(String jwtStr) {
JWTResult jwtResult = new JWTResult();
try {
Claims claims = parseJWT(jwtStr);
jwtResult.setSuccess(true);
jwtResult.setClaims(claims);
} catch (ExpiredJwtException e) { // token超时
jwtResult.setErrCode(JWT_ERRCODE_EXPIRE);
jwtResult.setSuccess(false);
} catch (SignatureException e) { // 校验失败
jwtResult.setErrCode(JWT_ERROR_FAIL);
jwtResult.setSuccess(false);
} catch (Exception e) {
jwtResult.setErrCode(JWT_ERROR_FAIL);
jwtResult.setSuccess(false);
}
return jwtResult;
}
/**
* 解析JWT
*/
public static Claims parseJWT(String token) throws Exception {
SecretKey secretKey = generalKey();
Claims body = Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(token)
.getBody();
return body;
}
/**
* 生成subject信息
* subject 要转换的对象
* java对象 ---> JSON
*/
public static String generalSubject(Object subject) {
String s = null;
try {
s = objectMapper.writeValueAsString(subject);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return s;
}
}
/**
* 结果对象
*/
public class JWTResult {
/**
* 错误编码
*/
private int errCode;
/**
* 是否成功,代表结果状态
*/
private boolean success;
/**
* 验证过程中payload中的数据
*/
private Claims claims;
public int getErrCode() {
return errCode;
}
public void setErrCode(int errCode) {
this.errCode = errCode;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public Claims getClaims() {
return claims;
}
public void setClaims(Claims claims) {
this.claims = claims;
}
public JWTResult(int errCode, boolean success, Claims claims) {
this.errCode = errCode;
this.success = success;
this.claims = claims;
}
public JWTResult() {
}
}
public class HttpClientUtil {
private HttpClientUtil() {
}
public static String doGet(String url, Map<String, String> param) {
// 创建Httpclient对象
CloseableHttpClient httpclient = HttpClients.createDefault();
String resultString = "";
CloseableHttpResponse response = null;
try {
// 创建uri
URIBuilder builder = new URIBuilder(url);
if (param != null) {
for (String key : param.keySet()) {
builder.addParameter(key, param.get(key));
}
}
URI uri = builder.build();
// 创建http GET请求
HttpGet httpGet = new HttpGet(uri);
// 执行请求
response = httpclient.execute(httpGet);
// 判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (response != null) {
response.close();
}
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
public static String doGet(String url) {
return doGet(url, null);
}
public static String doPost(String url, Map<String, String> param) {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建参数列表
if (param != null) {
List<NameValuePair> paramList = new ArrayList<>();
for (String key : param.keySet()) {
paramList.add(new BasicNameValuePair(key, param.get(key)));
}
// 模拟表单
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
httpPost.setEntity(entity);
}
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return resultString;
}
public static String doPost(String url) {
return doPost(url, null);
}
public static String doPostJson(String url, String json) {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建请求内容
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
httpPost.setEntity(entity);
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return resultString;
}
}
6.4 拦截器
@Component
public class AuthInterceptor extends HandlerInterceptorAdapter {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//拦截代码
HandlerMethod hm = (HandlerMethod) handler;
LoginRequired methodAnnotation = hm.getMethodAnnotation(LoginRequired.class);
//是否拦截
if (methodAnnotation == null) {
return true;
}
boolean b = methodAnnotation.loginSuccess();
if (!b) { // 可以不登陆 必须要验证token
String cookieValue = CookieUtil.getCookieValue(request, "token");
String s = HttpClientUtil.doGet("http://validate.cy.com/validate?token=" + cookieValue);
if (s.equals("success")) {
request.setAttribute("msg", "success");
request.setAttribute("username", "cy");
} else {
request.setAttribute("msg", "fail");
}
}
return true;
}
}
@Configuration
public class MyInterceptor implements WebMvcConfigurer {
@Autowired
private AuthInterceptor authInterceptor;
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/**");
}
}
6.5 controller
@Controller
@RequestMapping("/")
public class MainController {
@RequestMapping("toMain")
@LoginRequired(loginSuccess = false)
public String toMain(HttpServletRequest request, Map map) {
return "main";
}
@RequestMapping("toCart")
@LoginRequired(loginSuccess = false)
public String toCart(HttpServletRequest request, Map map) {
return "cart";
}
}
@Controller
@RequestMapping("/")
public class LoginController {
@RequestMapping("toLogin")
public String toLogin(String ReturnUrl, Map map) {
map.put("ReturnUrl", ReturnUrl);
return "login";
}
@RequestMapping("login")
@ResponseBody
public String login(String username, String password, HttpServletRequest request, HttpServletResponse response) {
String msg = "";
if (username.equals("zhangsan")) {
//创建jwt的token
String token = JWTUtils.creatJWT(UUID.randomUUID().toString(), "cy", "cy", 0);
CookieUtil.setCookie(request,response,"token",token);
msg = "success";
} else {
msg = "fail";
}
return msg;
}
}
/**
* 认证中心
*/
@Controller
@RequestMapping("/")
public class ValidateController {
@RequestMapping("validate")
@ResponseBody
public String validate(String token) {
//校验 token
JWTResult result = JWTUtils.validateJWT(token);
if (result.isSuccess()) {
return "success";
} else {
return "fail";
}
}
}
6.6 页面
login.html
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>登录</title>
<script th:src="@{/jquery-2.2.1.min.js}"></script>
<script>
function submit() {
$.post("login", $("#loginForm").serialize(), function (data) {
//验证 token 是否为空 或者 存在异常
if (data == "fail") {
alert("用户名或密码有误");
} else {
console.log(token);
window.location.href = $("#ReturnUrl").val();
}
});
}
</script>
</head>
<body>
<table>
<form id="loginForm">
<tr>
<td>用户名:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<input type="text" hidden="hidden" th:value="${ReturnUrl}" id="ReturnUrl">
</form>
</table>
<input type="button" style="" value="提交" onclick="submit()">
</body>
</html>
main.html
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>首页</title>
</head>
<body>
<h1>首页</h1>
<a th:if="${msg == 'fail'}" href="http://login.cy.com/toLogin?ReturnUrl=http://main.cy.com/toMain">您好,请登录</a>
<a th:if="${msg == 'success'}" href="http://login.cy.com/toLogin?ReturnUrl=http://main.cy.com/toMain">欢迎,</a><span th:text="${username}"></span>
</body>
</html>
cart.html
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>购物车</title>
</head>
<body>
<h1>购物车</h1>
<a th:if="${msg == 'fail'}" href="http://login.cy.com/toLogin?ReturnUrl=http://main.cy.com/toMain">您好,请登录</a>
<a th:if="${msg == 'success'}" href="http://login.cy.com/toLogin?ReturnUrl=http://main.cy.com/toMain">欢迎,</a><span th:text="${username}"></span>
</body>
</html>
1826

被折叠的 条评论
为什么被折叠?



