单点登录系统是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。它包括可以将这次主要的登录映射到其他应用中用于同一个用户的登录的机制。它是目前比较流行的企业业务整合的解决方案之一。
中间sso这一块就是单点登录系统的逻辑,单点登录系统是给其他客户端(portal端、安卓端、ios端)使用
首次登录生成token存储在redis中时效为5分钟,五分钟内如果有操作会刷新时效,无操作则在操作时会跳转到登录页面,sso只负责登录、注册、校验token时效不负责跳转,由客户端调用判断sso返回结果进行跳转。
系统结构:
Redis工具类:
package com.sso.sso.util;
import com.alibaba.fastjson.JSON;
import com.google.gson.JsonObject;
import com.sso.sso.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import java.util.concurrent.TimeUnit;
@Component
public class RedisUtil {
@Autowired
private RedisTemplate<String,String> redisTemplate;
//设置key-value
public void set(String key,Object value){
String valueString = JSON.toJSONString(value);
redisTemplate.opsForValue().set(key,valueString);
}
//设置key-value 加时长
public void set(String key,Object value,int seconds){
String valueString = JSON.toJSONString(value);
redisTemplate.opsForValue().set(key,valueString,seconds, TimeUnit.SECONDS);
}
//获取value
public String get(String key){
return redisTemplate.opsForValue().get(key);
}
//获取value转对象
public Object get(String key,Class cls){
String value = redisTemplate.opsForValue().get(key);
return JSON.parseObject(value,cls);
}
//获取value转对象
public void delete(String key){
redisTemplate.delete(key);
}
public void expire(String key,int seconds) {
redisTemplate.expire(key,seconds,TimeUnit.SECONDS);
}
}
JPA:
package com.sso.sso.repository;
import com.sso.sso.pojo.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User,Integer> {
User findUserByUserName(String userName);
}
SERVICE:
package com.sso.sso.service.impl;
import com.sso.sso.pojo.User;
import com.sso.sso.repository.UserRepository;
import com.sso.sso.service.UserService;
import com.sso.sso.util.RedisUtil;
import io.lettuce.core.RedisClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import java.util.UUID;
@Service("UserService")
public class UserServiceImpl implements UserService {
@Autowired
private RedisUtil redisUtil;
@Autowired
private UserRepository repository;
@Override
public void registerUser(String userName,String password) {
User user = new User(userName,DigestUtils.md5DigestAsHex(password.getBytes()));
repository.save(user);
}
@Override
public String userLogin(String userName,String password) {
String token = String.valueOf(UUID.randomUUID());
User user = repository.findUserByUserName(userName);
try{
if(null !=user && user.getUserPassword().equals(DigestUtils.md5DigestAsHex(password.getBytes()))){
redisUtil.set(token+":"+user.getUserName(),user,5*60);
return token;
}
}catch (Exception e){
return "登录失败";
}
return "登录失败";
}
@Override
public String checkToken(String userName, String token) {
String key = token+":"+userName;
Object obj = redisUtil.get(key,User.class);
if(null != obj && ((User)obj).getUserName().equals(userName)){
redisUtil.expire(key,5*60);
return token;
}
return "登录过期,请重新登录";
}
}
CONTROLLER:
package com.sso.sso.controller;
import com.sso.sso.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/register")
public String register(String userName,String password){
userService.registerUser(userName,password);
return "Ok";
}
@RequestMapping("/checkLogin")
public String checkLogin(String userName, String token){
return userService.checkToken(userName,token);
}
@RequestMapping("/login")
public String login(String userName, String password){
String result = userService.userLogin(userName,password);
return result;
}
}
User.java
package com.sso.sso.pojo;
import lombok.Data;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.*;
import java.util.Date;
@Data
@Entity
@DynamicInsert
@DynamicUpdate
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer userId;
private String userName;
private String userPassword;
@Temporal(TemporalType.TIMESTAMP)
private Date createTime;
@Temporal(TemporalType.TIMESTAMP)
private Date updateTime;
public User() {
}
public User(String userName, String userPassword) {
this.userName = userName;
this.userPassword = userPassword;
}
}
application配置文件:
spring:
jpa:
show-sql: true
datasource:
driver-class-name: com.mysql.jdbc.Driver
username: root
password: ppc123456
url: jdbc:mysql://localhost:3306/****?characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
redis:
database: 0
host: 192.168.**.**
port: 6379
password:
jedis:
pool:
max-active: 8
max-wait: -1
min-idle: 0
max-idle: 8
timeout: 50000
user表
CREATE TABLE `user` (
`user_id` int(11) NOT NULL AUTO_INCREMENT,
`user_name` varchar(64) NOT NULL COMMENT '名字',
`user_password` varchar(64) NOT NULL,
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2004 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户表';
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.sso</groupId>
<artifactId>sso</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sso</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.6</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.16.Final</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
项目代码github地址:https://github.com/TBirdsWR/sso.git