完成sso单点登录demo

This commit is contained in:
fanxb 2019-03-14 17:29:21 +08:00
parent 6dc9c359e3
commit a11ed17417
17 changed files with 137 additions and 42 deletions

View File

@ -28,6 +28,22 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>

View File

@ -3,6 +3,9 @@ package com.infinova.sso.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
@ -12,11 +15,13 @@ import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;
import java.time.Duration;
@ -31,6 +36,28 @@ import java.time.Duration;
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
private static Logger logger = LoggerFactory.getLogger(RedisConfig.class);
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private int timeout;
@Value("${spring.redis.database}")
private int database;
@Value("${spring.redis.jedis.pool.max-idle}")
private int maxIdle;
@Value("${spring.redis.jedis.pool.min-idle}")
private int minIdle;
@Value("${spring.redis.jedis.pool.max-wait}")
private long maxWaitMillis;
@Value("${spring.redis.jedis.pool.max-active}")
private int maxActive;
/**
* 设置缓存管理器这里可以配置默认过期时间等
*
@ -38,11 +65,11 @@ public class RedisConfig extends CachingConfigurerSupport {
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
public CacheManager cacheManager(JedisConnectionFactory jedisConnectionFactory) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration
.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(60));
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(jedisConnectionFactory);
RedisCacheManager manager = new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
return manager;
}
@ -64,4 +91,27 @@ public class RedisConfig extends CachingConfigurerSupport {
template.afterPropertiesSet();
return template;
}
@Bean
public JedisConnectionFactory jedisConnectionFactory() {
logger.info("jedisConnectionFactory:初始化了");
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxIdle(maxIdle);
config.setMinIdle(minIdle);
config.setMaxWaitMillis(maxWaitMillis);
config.setMaxTotal(maxActive);
//链接耗尽时是否阻塞默认true
config.setBlockWhenExhausted(true);
//是否启用pool的jmx管理功能默认true
config.setJmxEnabled(true);
JedisConnectionFactory factory = new JedisConnectionFactory();
factory.setPoolConfig(config);
factory.setHostName(host);
factory.setPort(port);
factory.setPassword(password);
factory.setDatabase(database);
factory.setTimeout(timeout);
return factory;
}
}

View File

@ -1,10 +1,8 @@
package com.infinova.sso.controller;
import com.alibaba.fastjson.JSONArray;
import com.infinova.sso.entity.ReturnEntity;
import com.infinova.sso.entity.User;
import com.infinova.sso.service.JwtService;
import com.infinova.sso.util.HttpUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -34,14 +32,13 @@ public class JwtController {
return ReturnEntity.successResult(token);
}
@PostMapping("/checkJwt")
@GetMapping("/checkJwt")
public ReturnEntity checkJwt(String token) {
return ReturnEntity.successResult(service.checkJwt(token));
}
@GetMapping("/inValid")
public ReturnEntity inValid() {
String token = HttpUtil.getData(JwtService.JWT_KEY);
public ReturnEntity inValid(String token) {
service.inValid(token);
return ReturnEntity.successResult(null);
}

View File

@ -1,8 +1,7 @@
package com.infinova.sso.util;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@ -18,20 +17,23 @@ import java.util.concurrent.TimeUnit;
public class RedisUtil {
private static final int DEFAULT_EXPIRE_TIME = 60 * 1000;
public static RedisTemplate<String, String> redisTemplate;
public static StringRedisTemplate redisTemplate;
@Autowired
public void setRedisTemplate(RedisTemplate<String, String> redisTemplate) {
public void setRedisTemplate(StringRedisTemplate redisTemplate) {
RedisUtil.redisTemplate = redisTemplate;
}
@Autowired
/**
* 设置键值对使用默认过期时间
*
* @param key
* @param value
*/
public static void set(String key, Object value) {
public static void set(String key, String value) {
set(key, value, DEFAULT_EXPIRE_TIME);
}
@ -42,8 +44,8 @@ public class RedisUtil {
* @param value value
* @param expireTime 过期时间
*/
public static void set(String key, Object value, long expireTime) {
redisTemplate.opsForValue().set(key, JSON.toJSONString(value));
public static void set(String key, String value, long expireTime) {
redisTemplate.opsForValue().set(key, value);
redisTemplate.expire(key, expireTime, TimeUnit.MILLISECONDS);
}

View File

@ -9,22 +9,22 @@ spring:
type: redis
redis:
database: 0
host: 192.168.1.100
host: 10.82.27.177
port: 6379
password:
# 连接超时时间ms)
timeout: 1000ms
timeout: 5000
# 高版本springboot中使用jedis或者lettuce
jedis:
pool:
# 连接池最大连接数(负值表示无限制)
max-active: 8
# 连接池最大阻塞等待时间(负值无限制)
max-wait: 5000ms
max-wait: 5000
# 最大空闲链接数
max-idle: 8
# 最小空闲链接数
min-idle: 0
min-idle: 1
mvc:
static-path-pattern: /static/**
# jwt过期时间单位分钟

View File

@ -25,9 +25,10 @@
} else {
//有token检查token是否还有效
$.get("/sso/checkJwt?token=" + localStorage.getItem("token"), function (res) {
if (res.code === 1) {
console.log(res);
if (res.data === true) {
alert('已登录,跳转到回调页面');
window.location.href = getUrlParam("redirect") + "&token=" + getToken();
window.location.href = getUrlParam("redirect") + "?token=" + localStorage.getItem("token");
} else {
goLogin();
}

View File

@ -25,9 +25,9 @@
data: JSON.stringify({name: name, password: password}),
success: function (res) {
if (res.code === 1) {
setToken(res.data);
localStorage.setItem("token", res.data);
alert("登录成功,跳转到回调地址");
window.location.href = getUrlParam("redirect") + "&token=" + res.data;
window.location.href = getUrlParam("redirect") + "?token=" + res.data;
} else {
alert("账号密码错误");
}

View File

@ -2,7 +2,6 @@ package com.example.sysa.controller;
import com.example.sysa.entity.ReturnEntity;
import com.example.sysa.entity.UserContext;
import com.example.sysa.filter.LoginFilter;
import com.example.sysa.util.HttpClient;
import com.example.sysa.util.UserContextHolder;
import org.springframework.beans.factory.annotation.Value;
@ -31,7 +30,7 @@ public class Main {
@RequestMapping("/logout")
public ReturnEntity logout() throws Exception {
UserContext context = UserContextHolder.get();
HttpClient.get(serverHost + "/clearToken?token=" + context.getToken());
HttpClient.get(serverHost + "/inValid?token=" + context.getToken());
return null;
}
}

View File

@ -17,8 +17,6 @@ import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
@ -76,7 +74,7 @@ public class LoginFilter implements Filter {
return false;
}
JSONObject object = HttpClient.get(serverHost + "/checkJwt?token=" + jwt);
return object.getInteger("code") == 1;
return object.getBoolean("data");
} catch (Exception e) {
logger.error("向认证中心请求失败", e);
return false;

View File

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title>系统A</title>
<title>系统</title>
</head>
<body>
<div id="currentHost"></div>
@ -14,16 +14,12 @@
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/Base64/1.0.2/base64.min.js"></script>
<script>
$('#currentHost').text(location.origin);
var token = getUrlParam("token");
if (token != null && token.trim().length > 0) {
localStorage.setItem("token", token);
}
test();
var info = localStorage.getItem("token").split(".")[1];
var userName = JSON.parse(window.atob(info)).name;
$('#loginStatus').text(userName);
$('#currentHost').text("当前ip端口" + location.origin);
//测试token是否有效
@ -38,7 +34,7 @@
//注销登录
function clearToken() {
$.get("/logout?token=" + getToken(), function (res) {
$.get("/logout?token=" + localStorage.getItem("token"), function (res) {
localStorage.removeItem("token");
goToLoginServer();
})
@ -46,14 +42,8 @@
function goToLoginServer() {
alert("当前无登录信息,跳转到认证中心");
location.href = encodeURI("http://localhost:8080/sso/static/index.html?order=checkLogin&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; //返回参数值
localStorage.setItem("redirect", location.href);
location.href = encodeURI("http://localhost:8080/sso/static/index.html?order=checkLogin&redirect=" + window.location.origin + "/static/redirect.html");
}
</script>

View File

@ -0,0 +1,24 @@
<!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>
//本页面用于回调中转
var token = getUrlParam("token");
localStorage.setItem("token", token);
location.replace(localStorage.getItem("redirect"))
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>
</body>
</html>

View File

@ -0,0 +1,2 @@
server:
port: 10011

View File

@ -0,0 +1,3 @@
server:
port: 10012

View File

@ -0,0 +1,5 @@
server:
port: 10001
spring:
application:
name: licensingservice

View File

@ -0,0 +1,2 @@
server:
port: 10012

View File

@ -0,0 +1,3 @@
server:
port: 10012

View File

@ -0,0 +1,3 @@
spring:
application:
name: organizationservice