no message
This commit is contained in:
parent
3917829968
commit
6dc9c359e3
@ -35,15 +35,8 @@ public class JwtController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/checkJwt")
|
@PostMapping("/checkJwt")
|
||||||
public ReturnEntity checkJwt(@RequestBody JSONArray tokenList) {
|
public ReturnEntity checkJwt(String token) {
|
||||||
return ReturnEntity.successResult(service.checkJwt(tokenList));
|
return ReturnEntity.successResult(service.checkJwt(token));
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/refreshJwt")
|
|
||||||
public ReturnEntity refreshJwt() {
|
|
||||||
String oldToken = HttpUtil.getData(JwtService.JWT_KEY);
|
|
||||||
String newToken = service.refreshJwt(oldToken);
|
|
||||||
return ReturnEntity.successResult(newToken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/inValid")
|
@GetMapping("/inValid")
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
package com.infinova.sso.entity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 类功能简述:
|
|
||||||
* 类功能详述:
|
|
||||||
*
|
|
||||||
* @author fanxb
|
|
||||||
* @date 2019/3/7 16:46
|
|
||||||
*/
|
|
||||||
public class JwtInfo {
|
|
||||||
private String secret;
|
|
||||||
private long lastRefreshTime;
|
|
||||||
|
|
||||||
public JwtInfo(String secret, long lastRefreshTime) {
|
|
||||||
this.secret = secret;
|
|
||||||
this.lastRefreshTime = lastRefreshTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSecret() {
|
|
||||||
return secret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSecret(String secret) {
|
|
||||||
this.secret = secret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getLastRefreshTime() {
|
|
||||||
return lastRefreshTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLastRefreshTime(long lastRefreshTime) {
|
|
||||||
this.lastRefreshTime = lastRefreshTime;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +1,16 @@
|
|||||||
package com.infinova.sso.service;
|
package com.infinova.sso.service;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
|
||||||
import com.auth0.jwt.JWT;
|
|
||||||
import com.infinova.sso.entity.JwtInfo;
|
|
||||||
import com.infinova.sso.entity.User;
|
import com.infinova.sso.entity.User;
|
||||||
import com.infinova.sso.exception.CustomException;
|
import com.infinova.sso.exception.CustomException;
|
||||||
import com.infinova.sso.util.HttpUtil;
|
|
||||||
import com.infinova.sso.util.JwtUtil;
|
import com.infinova.sso.util.JwtUtil;
|
||||||
|
import com.infinova.sso.util.RedisUtil;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.servlet.http.Cookie;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 类功能简述:
|
* 类功能简述:
|
||||||
@ -33,18 +28,14 @@ public class JwtService {
|
|||||||
private Logger logger = LoggerFactory.getLogger(JwtService.class);
|
private Logger logger = LoggerFactory.getLogger(JwtService.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 存储jwt与secret对应关系
|
* jwt token超时时间,单位ms
|
||||||
*/
|
*/
|
||||||
private static Map<String, JwtInfo> jwtMap = new ConcurrentHashMap<>();
|
private static int expireTime;
|
||||||
|
|
||||||
/**
|
@Value("${jwt_expire_time}")
|
||||||
* jwt token超时时间,单位s
|
public void setExpireTime(int expireTime) {
|
||||||
*/
|
JwtService.expireTime = expireTime * 60 * 1000;
|
||||||
private static final int TIME_OUT = 60 * 60;
|
}
|
||||||
/**
|
|
||||||
* 在此时间段内,一个jwt不能重复刷新
|
|
||||||
*/
|
|
||||||
private static final int REFRESH_INTERVAL = 5 * 60 * 1000;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description:登录获取token
|
* Description:登录获取token
|
||||||
@ -58,77 +49,48 @@ public class JwtService {
|
|||||||
//进行登录校验
|
//进行登录校验
|
||||||
try {
|
try {
|
||||||
if (user.getName().equalsIgnoreCase(user.getPassword())) {
|
if (user.getName().equalsIgnoreCase(user.getPassword())) {
|
||||||
String token = this.generateNewJwt(user.getName());
|
return this.generateNewJwt(user.getName());
|
||||||
setCookie(token, TIME_OUT);
|
|
||||||
return token;
|
|
||||||
} else {
|
} else {
|
||||||
logger.info("账号密码错误:{}{}", user.getName(), user.getPassword());
|
logger.info("账号密码错误:{}{}", user.getName(), user.getPassword());
|
||||||
throw new CustomException("账号密码错误");
|
throw new CustomException("账号密码错误");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.info("账号密码错误:{},{}", user.getName(), user.getPassword());
|
logger.info("账号密码错误:{},{}", user.getName(), user.getPassword());
|
||||||
throw new CustomException("账号密码错误");
|
throw new CustomException(e, "账号密码错误");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Description:刷新token
|
|
||||||
*
|
|
||||||
* @return java.lang.String
|
|
||||||
* @author fanxb
|
|
||||||
* @date 2019/3/5 11:06
|
|
||||||
*/
|
|
||||||
public String refreshJwt(String token) {
|
|
||||||
try {
|
|
||||||
JwtInfo info = jwtMap.get(token);
|
|
||||||
Long nowTime = System.currentTimeMillis();
|
|
||||||
if (nowTime - info.getLastRefreshTime() < REFRESH_INTERVAL) {
|
|
||||||
throw new CustomException("token刷新间隔过短");
|
|
||||||
}
|
|
||||||
info.setLastRefreshTime(nowTime);
|
|
||||||
String id = JwtUtil.decode(token, info.getSecret()).get("loginId").asString();
|
|
||||||
String newToken = generateNewJwt(id);
|
|
||||||
setCookie(newToken, TIME_OUT);
|
|
||||||
return newToken;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new CustomException(e, "token校验失败");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description: 生成新的jwt,并放入jwtMap中
|
* Description: 生成新的jwt,并放入jwtMap中
|
||||||
*
|
*
|
||||||
* @return java.lang.String
|
* @return java.lang.String
|
||||||
* @author fanxb
|
* @author fanxb
|
||||||
* @date 2019/3/5 10:44
|
* date 2019/3/5 10:44
|
||||||
*/
|
*/
|
||||||
private String generateNewJwt(String name) {
|
private String generateNewJwt(String name) {
|
||||||
String secret = UUID.randomUUID().toString().replaceAll("-", "");
|
String secret = UUID.randomUUID().toString().replaceAll("-", "");
|
||||||
String token = JwtUtil.encode(name, secret, TIME_OUT);
|
String token = JwtUtil.encode(name, secret, expireTime);
|
||||||
jwtMap.put(token, new JwtInfo(secret, 0));
|
RedisUtil.set(token, secret, expireTime);
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description:检查jwt有效性,返回失效jwt
|
* Description:检查jwt有效性
|
||||||
*
|
*
|
||||||
* @return List<String> 失效jwt列表
|
* @return Boolean
|
||||||
* @author fanxb
|
* @author fanxb
|
||||||
* @date 2019/3/4 18:47
|
* @date 2019/3/4 18:47
|
||||||
*/
|
*/
|
||||||
public List<String> checkJwt(JSONArray tokens) {
|
public Boolean checkJwt(String jwt) {
|
||||||
List<String> res = new ArrayList<>();
|
|
||||||
tokens.forEach(item -> {
|
|
||||||
String jwt = (String) item;
|
|
||||||
try {
|
try {
|
||||||
String secret = jwtMap.get(jwt).getSecret();
|
String secret = RedisUtil.redisTemplate.opsForValue().get(jwt);
|
||||||
JwtUtil.decode(jwt, secret);
|
JwtUtil.decode(jwt, secret);
|
||||||
|
return true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
res.add(jwt);
|
return false;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -138,43 +100,7 @@ public class JwtService {
|
|||||||
* @date 2019/3/4 19:58
|
* @date 2019/3/4 19:58
|
||||||
*/
|
*/
|
||||||
public void inValid(String jwt) {
|
public void inValid(String jwt) {
|
||||||
jwtMap.remove(jwt);
|
RedisUtil.delete(jwt);
|
||||||
setCookie("", 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Description:定时检查过期的jwt,并从map中删除
|
|
||||||
*
|
|
||||||
* @author fanxb
|
|
||||||
* @date 2019/3/5 18:16
|
|
||||||
*/
|
|
||||||
@Scheduled(fixedRate = 10 * 1000)
|
|
||||||
private void cleanJwtMap() {
|
|
||||||
Date now = new Date();
|
|
||||||
Set<String> keys = jwtMap.keySet();
|
|
||||||
keys.forEach(item -> {
|
|
||||||
if (now.getTime() > JWT.decode(item).getExpiresAt().getTime()) {
|
|
||||||
jwtMap.remove(item);
|
|
||||||
logger.info("清理掉了:{}", item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Description: 写入jwt token到cookie
|
|
||||||
*
|
|
||||||
* @param token token
|
|
||||||
* @param maxAge 失效时间 单位s
|
|
||||||
* @return void
|
|
||||||
* @author fanxb
|
|
||||||
* @date 2019/3/5 18:43
|
|
||||||
*/
|
|
||||||
private void setCookie(String token, int maxAge) {
|
|
||||||
Cookie cookie = new Cookie(JWT_KEY, token);
|
|
||||||
cookie.setMaxAge(maxAge);
|
|
||||||
cookie.setPath("/");
|
|
||||||
HttpUtil.getResponse().addCookie(cookie);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ public class JwtUtil {
|
|||||||
Algorithm algorithm = Algorithm.HMAC256(secret);
|
Algorithm algorithm = Algorithm.HMAC256(secret);
|
||||||
String token = JWT.create()
|
String token = JWT.create()
|
||||||
//设置过期时间为一个小时
|
//设置过期时间为一个小时
|
||||||
.withExpiresAt(new Date(System.currentTimeMillis() + timeOut * 1000))
|
.withExpiresAt(new Date(System.currentTimeMillis() + timeOut))
|
||||||
//设置负载
|
//设置负载
|
||||||
.withClaim("name", name)
|
.withClaim("name", name)
|
||||||
.sign(algorithm);
|
.sign(algorithm);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
server:
|
server:
|
||||||
port: 8081
|
port: 8080
|
||||||
servlet:
|
servlet:
|
||||||
context-path: /sso
|
context-path: /sso
|
||||||
spring:
|
spring:
|
||||||
@ -9,7 +9,7 @@ spring:
|
|||||||
type: redis
|
type: redis
|
||||||
redis:
|
redis:
|
||||||
database: 0
|
database: 0
|
||||||
host: 10.82.27.177
|
host: 192.168.1.100
|
||||||
port: 6379
|
port: 6379
|
||||||
password:
|
password:
|
||||||
# 连接超时时间(ms)
|
# 连接超时时间(ms)
|
||||||
@ -25,4 +25,8 @@ spring:
|
|||||||
max-idle: 8
|
max-idle: 8
|
||||||
# 最小空闲链接数
|
# 最小空闲链接数
|
||||||
min-idle: 0
|
min-idle: 0
|
||||||
|
mvc:
|
||||||
|
static-path-pattern: /static/**
|
||||||
|
# jwt过期时间,单位分钟
|
||||||
|
jwt_expire_time: 60
|
||||||
|
|
||||||
|
@ -5,40 +5,28 @@
|
|||||||
<title>认证中心</title>
|
<title>认证中心</title>
|
||||||
</head>
|
</head>
|
||||||
<div style="text-align: center;">这里是认证中心主页</div>
|
<div style="text-align: center;">这里是认证中心主页</div>
|
||||||
<div>
|
|
||||||
<button onclick="clearToken()">清除token</button>
|
|
||||||
</div>
|
|
||||||
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
|
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
|
||||||
<script src="main.js"></script>
|
<script src="main.js"></script>
|
||||||
<script src="https://cdn.bootcss.com/Base64/1.0.2/base64.js"></script>
|
<script src="https://cdn.bootcss.com/Base64/1.0.2/base64.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$('#loginStatus').html(getUserName())
|
|
||||||
|
|
||||||
function clearToken() {
|
|
||||||
delete window.localStorage.token;
|
|
||||||
}
|
|
||||||
|
|
||||||
var order = getUrlParam("order");
|
var order = getUrlParam("order");
|
||||||
switch (order) {
|
switch (order) {
|
||||||
case "checkLogin":
|
case "checkLogin":
|
||||||
checkLogin();
|
checkLogin();
|
||||||
break;
|
break;
|
||||||
case "updateToken":
|
|
||||||
updateToken();
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
console.log("不支持的order:" + order);
|
console.log("不支持的order:" + order);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkLogin() {
|
function checkLogin() {
|
||||||
var token = getToken();
|
var token = localStorage.getItem("token");
|
||||||
if (token == null) {
|
if (token == null || token.length == 0) {
|
||||||
goLogin();
|
goLogin();
|
||||||
} else {
|
} else {
|
||||||
//有token,检查token是否还有效
|
//有token,检查token是否还有效
|
||||||
$.get("/checkToken?token=" + getToken(), function (res) {
|
$.get("/sso/checkJwt?token=" + localStorage.getItem("token"), function (res) {
|
||||||
if (res.code === 1) {
|
if (res.code === 1) {
|
||||||
alert('以登录,跳转到回调页面');
|
alert('已登录,跳转到回调页面');
|
||||||
window.location.href = getUrlParam("redirect") + "&token=" + getToken();
|
window.location.href = getUrlParam("redirect") + "&token=" + getToken();
|
||||||
} else {
|
} else {
|
||||||
goLogin();
|
goLogin();
|
||||||
@ -48,16 +36,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function goLogin() {
|
function goLogin() {
|
||||||
// alert("无认证信息,即将跳转到登录页面");
|
alert("无认证信息,即将跳转到登录页面");
|
||||||
window.location.href = encodeURI("/login.html?redirect=" + getUrlParam("redirect"));
|
window.location.href = encodeURI("./login.html?redirect=" + getUrlParam("redirect"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateToken() {
|
|
||||||
var token = getUrlParam("token");
|
|
||||||
setToken(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -11,26 +11,23 @@
|
|||||||
<button id="login" onclick="doLogin()">登录</button>
|
<button id="login" onclick="doLogin()">登录</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
|
|
||||||
<script src="main.js"></script>
|
<script src="main.js"></script>
|
||||||
<script src="https://cdn.bootcss.com/Base64/1.0.2/base64.min.js"></script>
|
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
function doLogin() {
|
function doLogin() {
|
||||||
var name = $('#name').val();
|
var name = $('#name').val();
|
||||||
var password = $('#password').val();
|
var password = $('#password').val();
|
||||||
password = window.btoa(password);
|
|
||||||
console.log(name, password);
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'post',
|
type: 'post',
|
||||||
url: "/sso/login",
|
url: "/sso/login",
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
data: JSON.stringify({loginId: name, password: password}),
|
data: JSON.stringify({name: name, password: password}),
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
if (res.code === 1) {
|
if (res.code === 1) {
|
||||||
setToken(res.data);
|
setToken(res.data);
|
||||||
// alert("登录成功,跳转到回调地址");
|
alert("登录成功,跳转到回调地址");
|
||||||
// window.location.href = getUrlParam("redirect") + "&token=" + res.data;
|
window.location.href = getUrlParam("redirect") + "&token=" + res.data;
|
||||||
} else {
|
} else {
|
||||||
alert("账号密码错误");
|
alert("账号密码错误");
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,3 @@
|
|||||||
function getToken() {
|
|
||||||
return window.localStorage.token || null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setToken(token) {
|
|
||||||
window.localStorage.token = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUserName() {
|
|
||||||
var token = getToken();
|
|
||||||
if (token == null) {
|
|
||||||
return "未登录";
|
|
||||||
} else {
|
|
||||||
var info = token.split(".")[1];
|
|
||||||
return JSON.parse(window.atob(info)).name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUrlParam(name) {
|
function getUrlParam(name) {
|
||||||
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象
|
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象
|
||||||
var r = window.location.search.substr(1).match(reg); //匹配目标参数
|
var r = window.location.search.substr(1).match(reg); //匹配目标参数
|
||||||
|
@ -5,6 +5,7 @@ import com.example.sysa.entity.UserContext;
|
|||||||
import com.example.sysa.filter.LoginFilter;
|
import com.example.sysa.filter.LoginFilter;
|
||||||
import com.example.sysa.util.HttpClient;
|
import com.example.sysa.util.HttpClient;
|
||||||
import com.example.sysa.util.UserContextHolder;
|
import com.example.sysa.util.UserContextHolder;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@ -18,16 +19,19 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
@RestController
|
@RestController
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
|
@Value("${sso_server}")
|
||||||
|
private String serverHost;
|
||||||
|
|
||||||
@RequestMapping("/test")
|
@RequestMapping("/test")
|
||||||
public ReturnEntity test() {
|
public ReturnEntity test() {
|
||||||
return new ReturnEntity(1, "通过验证", null);
|
return new ReturnEntity(1, "通过验证", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@RequestMapping("/logout")
|
@RequestMapping("/logout")
|
||||||
public ReturnEntity logout() throws Exception {
|
public ReturnEntity logout() throws Exception {
|
||||||
UserContext context = UserContextHolder.get();
|
UserContext context = UserContextHolder.get();
|
||||||
HttpClient.get("http://localhost:8080/clearToken?token="+context.getToken());
|
HttpClient.get(serverHost + "/clearToken?token=" + context.getToken());
|
||||||
LoginFilter.tokenMap.remove(context.getToken());
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,4 +44,12 @@ public class ReturnEntity {
|
|||||||
public void setData(Object data) {
|
public void setData(Object data) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ReturnEntity successResult(Object data) {
|
||||||
|
return new ReturnEntity(1, "", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ReturnEntity failedResult(String message) {
|
||||||
|
return new ReturnEntity(0, message, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,9 @@ import com.example.sysa.entity.ReturnEntity;
|
|||||||
import com.example.sysa.entity.UserContext;
|
import com.example.sysa.entity.UserContext;
|
||||||
import com.example.sysa.util.HttpClient;
|
import com.example.sysa.util.HttpClient;
|
||||||
import com.example.sysa.util.UserContextHolder;
|
import com.example.sysa.util.UserContextHolder;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.Base64Utils;
|
import org.springframework.util.Base64Utils;
|
||||||
|
|
||||||
@ -29,11 +32,10 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
@WebFilter(urlPatterns = "/**", filterName = "loginFilter")
|
@WebFilter(urlPatterns = "/**", filterName = "loginFilter")
|
||||||
public class LoginFilter implements Filter {
|
public class LoginFilter implements Filter {
|
||||||
|
|
||||||
public static final Map<String, Long> tokenMap = new ConcurrentHashMap<>();
|
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
/**
|
|
||||||
* 10s内认为报错在tokenMap中的token有效,避免频繁请求认证中心验证token有效性
|
@Value("${sso_server}")
|
||||||
*/
|
private String serverHost;
|
||||||
private static final int EXPIRE_TIME = 10 * 1000;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(FilterConfig filterConfig) throws ServletException {
|
public void init(FilterConfig filterConfig) throws ServletException {
|
||||||
@ -53,26 +55,8 @@ public class LoginFilter implements Filter {
|
|||||||
filterChain.doFilter(servletRequest, servletResponse);
|
filterChain.doFilter(servletRequest, servletResponse);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boolean isOk = false;
|
String token = httpServletRequest.getParameter("token");
|
||||||
String token = "";
|
if (this.check(token)) {
|
||||||
try {
|
|
||||||
//如果token未缓存或距离上次检查有效性超过1分钟,向认证中心请求检查有效性
|
|
||||||
token = httpServletRequest.getParameter("token");
|
|
||||||
Long lastCheckTime = tokenMap.get(token);
|
|
||||||
if (lastCheckTime == null || System.currentTimeMillis() - lastCheckTime > EXPIRE_TIME) {
|
|
||||||
JSONObject object = HttpClient.get("http://localhost:8080/checkToken?token=" + token);
|
|
||||||
if (object.getInteger("code") == 1) {
|
|
||||||
isOk = true;
|
|
||||||
tokenMap.put(token, System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//token有效,且未过期
|
|
||||||
isOk = true;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
if (isOk) {
|
|
||||||
//token和用户id保存到userContextholder
|
//token和用户id保存到userContextholder
|
||||||
String str = new String(Base64Utils.decodeFromString(token.split("\\.")[1]));
|
String str = new String(Base64Utils.decodeFromString(token.split("\\.")[1]));
|
||||||
UserContext context = new UserContext(JSON.parseObject(str).getString("name"), token);
|
UserContext context = new UserContext(JSON.parseObject(str).getString("name"), token);
|
||||||
@ -84,6 +68,19 @@ public class LoginFilter implements Filter {
|
|||||||
response.setCharacterEncoding("utf-8");
|
response.setCharacterEncoding("utf-8");
|
||||||
response.getWriter().write(JSON.toJSONString(new ReturnEntity(-1, "未登录", null)));
|
response.getWriter().write(JSON.toJSONString(new ReturnEntity(-1, "未登录", null)));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean check(String jwt) {
|
||||||
|
try {
|
||||||
|
if (jwt == null || jwt.trim().length() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
JSONObject object = HttpClient.get(serverHost + "/checkJwt?token=" + jwt);
|
||||||
|
return object.getInteger("code") == 1;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("向认证中心请求失败", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
server.port=8081
|
|
||||||
spring.mvc.static-path-pattern=/static/**
|
|
6
1.SSO单点登录/sys-a/src/main/resources/application.yml
Normal file
6
1.SSO单点登录/sys-a/src/main/resources/application.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
server:
|
||||||
|
port: 8081
|
||||||
|
spring:
|
||||||
|
mvc:
|
||||||
|
static-path-pattern: /static/**
|
||||||
|
sso_server: http://localhost:8080/sso
|
@ -5,25 +5,30 @@
|
|||||||
<title>系统A</title>
|
<title>系统A</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div style="align-content: center">这里是系统A主页面</div>
|
<div id="currentHost"></div>
|
||||||
<div style="align-content: center">当前登录用户:<span id="loginStatus"></span></div>
|
<div style="align-content: center">当前登录用户:<span id="loginStatus"></span></div>
|
||||||
<div>
|
<div>
|
||||||
<button onclick="test()">测试接口访问</button>
|
<button onclick="test()">测试接口访问</button>
|
||||||
<button onclick="clearToken()">注销登录</button>
|
<button onclick="clearToken()">注销登录</button>
|
||||||
</div>
|
</div>
|
||||||
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
|
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
|
||||||
<script src="/static/main.js"></script>
|
|
||||||
<script src="https://cdn.bootcss.com/Base64/1.0.2/base64.min.js"></script>
|
<script src="https://cdn.bootcss.com/Base64/1.0.2/base64.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$('#loginStatus').text(getUserName());
|
$('#currentHost').text(location.origin);
|
||||||
if (getToken() == null) {
|
var token = getUrlParam("token");
|
||||||
goToLoginServer();
|
if (token != null && token.trim().length > 0) {
|
||||||
|
localStorage.setItem("token", token);
|
||||||
}
|
}
|
||||||
|
|
||||||
test();
|
test();
|
||||||
|
|
||||||
|
var info = localStorage.getItem("token").split(".")[1];
|
||||||
|
var userName = JSON.parse(window.atob(info)).name;
|
||||||
|
$('#loginStatus').text(userName);
|
||||||
|
|
||||||
|
|
||||||
|
//测试token是否有效
|
||||||
function test() {
|
function test() {
|
||||||
$.get("/test?token=" + getToken(), function (res) {
|
$.get("/test?token=" + localStorage.getItem("token"), function (res) {
|
||||||
if (res.code === 1) {
|
if (res.code === 1) {
|
||||||
} else {
|
} else {
|
||||||
goToLoginServer();
|
goToLoginServer();
|
||||||
@ -34,14 +39,21 @@
|
|||||||
//注销登录
|
//注销登录
|
||||||
function clearToken() {
|
function clearToken() {
|
||||||
$.get("/logout?token=" + getToken(), function (res) {
|
$.get("/logout?token=" + getToken(), function (res) {
|
||||||
|
localStorage.removeItem("token");
|
||||||
goToLoginServer();
|
goToLoginServer();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function goToLoginServer() {
|
function goToLoginServer() {
|
||||||
alert("当前无登录信息,跳转到认证中心");
|
alert("当前无登录信息,跳转到认证中心");
|
||||||
location.href = encodeURI("http://localhost:8080?order=checkLogin&redirect=" + window.location.origin
|
location.href = encodeURI("http://localhost:8080/sso/static/index.html?order=checkLogin&redirect=" + window.location.href);
|
||||||
+ "/static/redirect.html?redirect=" + window.location.href);
|
}
|
||||||
|
|
||||||
|
function getUrlParam(name) {
|
||||||
|
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象
|
||||||
|
var r = window.location.search.substr(1).match(reg); //匹配目标参数
|
||||||
|
if (r != null) return unescape(r[2]);
|
||||||
|
return null; //返回参数值
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
function getToken() {
|
|
||||||
return window.localStorage.token || null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setToken(token) {
|
|
||||||
window.localStorage.token = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUserName() {
|
|
||||||
var token = getToken();
|
|
||||||
if (token == null) {
|
|
||||||
return "未登录";
|
|
||||||
} else {
|
|
||||||
var info = token.split(".")[1];
|
|
||||||
return JSON.parse(window.atob(info)).name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUrlParam(name) {
|
|
||||||
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象
|
|
||||||
var r = window.location.search.substr(1).match(reg); //匹配目标参数
|
|
||||||
if (r != null) return unescape(r[2]);
|
|
||||||
return null; //返回参数值
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>登录成功回调地址</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
|
|
||||||
<script src="/static/main.js"></script>
|
|
||||||
<script src="https://cdn.bootcss.com/Base64/1.0.2/base64.min.js"></script>
|
|
||||||
<script>
|
|
||||||
var token = getUrlParam("token");
|
|
||||||
setToken(token);
|
|
||||||
// alert("认证成功,准备跳回登录登录前访问地址");
|
|
||||||
window.location.href = getUrlParam("redirect");
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
Loading…
x
Reference in New Issue
Block a user