springdatajpa单点登录(sso)

本文介绍了使用SpringDataJPA和Redis来实现单点登录(SSO)的详细过程,包括项目结构、实体类、DAO层、Redis操作、Service层、工具类设置以及登录页面和控制器的实现。通过示例展示了如何在不同浏览器间实现SSO的效果。
摘要由CSDN通过智能技术生成

springdatajpa+Redis实现单点登录(sso)

项目结构

在这里插入图片描述

实体类

package com.data.pojo;

import lombok.Data;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * Created by Administrator on 2019/11/18.
 */
@Data
@Entity
@Table(name = "user")
public class User {
    @Id
    @Column(name = "id",unique = true,nullable = false)
    private int id;
    @Column(name = "username",nullable = false)
    private  String username;
    @Column(name = "password",nullable = false)
    private String  password;




}

dao层

package com.data.dao;

import com.data.pojo.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

/**
 * Created by Administrator on 2019/11/18.
 */
@Repository
public interface UserDao extends JpaRepository<User,Integer> {
   public User findByUsernameAndPassword(String username,String password);
}

redis 层

jedisdao

package com.data.redis;

public interface JedisDao {

    //查
    public String getValue(String key);
    //删
    public Long delValue(String key);
    //增
    public String setValue(String key, String value);
    //设置时间
    public Long expire(String key, int seconds);
}

JedisDaoImpl

package com.data.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

@Component
public class JedisDaoImpl implements JedisDao{

    //连接池
    @Autowired
    private JedisPool jedisPool;

    @Override
    public String getValue(String key) {
        Jedis jedis = jedisPool.getResource();
        String value = jedis.get(key);
        jedis.close();
        return value;
    }

    @Override
    public Long delValue(String key) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.del(key);
        jedis.close();
        return result;
    }

    @Override
    public String setValue(String key, String value) {
        Jedis jedis = jedisPool.getResource();
        String str = jedis.set(key, value);
        jedis.close();
        return str;
    }

    @Override
    public Long expire(String key,int seconds) {
        Jedis jedis = jedisPool.getResource();
        Long time = jedis.expire(key, seconds);
        jedis.close();
        return time;
    }
}

service层

package com.data.service;

import com.data.dao.UserDao;
import com.data.pojo.User;
import com.data.redis.JedisDao;
import com.data.util.CookieUtils;
import com.data.util.JsonUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Service
public class UserServiceImpl{
    @Autowired
    private UserDao userDao;

    @Autowired
    private JedisDao jedisDao;

    @Value("${REDIS_KEY}")   //从配置文件中取值
    private String REDIS_KEY;

    private Map<Integer,String> userInfo = new HashMap<>();


    public Object getall(){
        String s= RandomStringUtils.randomAlphanumeric(10);
        if (jedisDao.getValue(s)!=null){
          return  jedisDao.getValue(s);
        }else{
            List<User>userList= userDao.findAll();
            jedisDao.setValue(s,JsonUtils.objectToJson(userList));
            return userList;
        }

    }

    public User userlogin(HttpServletRequest request, HttpServletResponse response, User u){
        //先进行数据库查询一遍
        User us=userDao.findByUsernameAndPassword(u.getUsername(),u.getPassword());
        //判断us是否为空
        if(us==null){
            return null;
        }
        //定义新的token
        String token="user_"+ UUID.randomUUID().toString();
        //判断map中是否存在该id
        if(!ObjectUtils.isEmpty(userInfo.get(us.getId()))){
            //从map中获得redis中的key
            String oldToken=userInfo.get(us.getId());
            //删除redis中老的值
            jedisDao.delValue(oldToken);
        }
        //将新的的key保存到map中
        userInfo.put(us.getId(),token);
        //将信息存入redis
        jedisDao.setValue(token,JsonUtils.objectToJson(us));
        //设置redis信息过期时间
        // redisTemplate.expire(token,5*60, TimeUnit.MILLISECONDS);
        //将token放入cookie中
        CookieUtils.setCookie(request,response,"USER_TOKEN",token,5*60,true);

        return us;
    }
    public String getUserByToken(HttpServletResponse response, HttpServletRequest request) {
        User us=null;
        //从cookie中取出用户token
        String token=CookieUtils.getCookieValue(request,"USER_TOKEN");
        String s = jedisDao.getValue(token);
        return s;
    }
}

util工具类

CookieUtils

package com.data.util;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

/**
 * 
 * Cookie 工具类
 *
 */
public final class CookieUtils {
 
    /**
     * 得到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 (UnsupportedEncodingException 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 (UnsupportedEncodingException 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 {
            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;
    }
 
}

JedisUtil

package com.data.util;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;

@Configuration
//链接redis 获取appliaction.yml 里的数据以spring.redis开头的方式
@ConfigurationProperties(prefix = "spring.redis")
public class JedisUtil {
    //属性名字和配置文件中必须一致,还要提供get和set方法
    private String host;  //读取到spring.redis.hostg.redis.port
    private int port;//sprin


    @Bean
    public JedisPool jedisPool(){
        JedisPool jedisPool = new JedisPool(host,port);
        System.out.println("已连接:"+host+"上的redis,端口号为:"+port);
        return jedisPool;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }
}

JsonUtils

package com.data.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.List;


public class JsonUtils {

    // 定义jackson对象
    private static final ObjectMapper MAPPER = new ObjectMapper();

    /**
     * 将对象转换成json字符串。
     * <p>Title: pojoToJson</p>
     * <p>Description: </p>
     * @param data
     * @return
     */
    public static String objectToJson(Object data) {
    	try {
			String string = MAPPER.writeValueAsString(data);
			return string;
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
    	return null;
    }
    
    /**
     * 将json结果集转化为对象
     * 
     * @param jsonData json数据
     * @param class 对象中的object类型
     * @return
     */
    public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
        try {
            T t = MAPPER.readValue(jsonData, beanType);
            return t;
        } catch (Exception e) {
        	e.printStackTrace();
        }
        return null;
    }
    
    /**
     * 将json数据转换成pojo对象list
     * <p>Title: jsonToList</p>
     * <p>Description: </p>
     * @param jsonData
     * @param beanType
     * @return
     */
    public static <T>List<T> jsonToList(String jsonData, Class<T> beanType) {
    	JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
    	try {
    		List<T> list = MAPPER.readValue(jsonData, javaType);
    		return list;
		} catch (Exception e) {
			e.printStackTrace();
		}
    	
    	return null;
    }
    
}

SimpleResponse

package com.data.util;

/**
 * 自定义响应类
 * @author lt
 */
public class SimpleResponse {
    private boolean success;
    private Object data;
    private String errCode;
    private String errMsg;
    private String errDesc;

    public SimpleResponse(Object data) {
        this.data = data;
        this.success=true;
    }

    public SimpleResponse(boolean success) {
        this.success = success;
    }

    public SimpleResponse(String errCode, String errMsg, String errDesc) {
        this.errCode = errCode;
        this.errMsg = errMsg;
        this.errDesc = errDesc;
        this.success=false;
    }

    public static SimpleResponse success(boolean success){
        return new SimpleResponse(success);
    }
    public static SimpleResponse success(Object data){
        return new SimpleResponse(data);
    }
    public static SimpleResponse error(String errCode, String errMsg, String errDesc){
        return new SimpleResponse(errCode,errMsg,errDesc);
    }

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public String getErrCode() {
        return errCode;
    }

    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }

    public String getErrMsg() {
        return errMsg;
    }

    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }

    public String getErrDesc() {
        return errDesc;
    }

    public void setErrDesc(String errDesc) {
        this.errDesc = errDesc;
    }
}

application.yml


spring:
  redis:
    database: 0    #redis的默认数据库为0
    host: 120.77.223.242  #链接redis的ip
    port: 6379  #链接redis的端口号
    password:   #链接redis的密码 默认为空
    jedis:
      pool:
        max-total: 200    #链接redis的总数目
        max-active: 100  #链接redis的最大
        max-idle: 8      #最大的链接数量
        min-idle: 5     #最小的链接数量
  datasource:
    url: jdbc:mysql://120.77.223.242:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
  jpa:
    show-sql: true
server:
  port: 8989

REDIS_KEY : uuuu

登录页面

login

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<center>
    <p>登录页面</p>
    <form method="POST" action="doLogin.html">
        <p><label>用户名:</label><input type="text" name="username" id="username"></p>
        <p><label>密码:</label><input type="password" name="password" id="password"></p>
        <p><input type="submit" style="color: blue">&nbsp;&nbsp;&nbsp;<input type="reset"></p>
        <p><span th:text="${error}"></span></p>
    </form>
</center>
</body>
</html>

index

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>欢迎</h1>
</body>
<script th:src="@{/js/jquery-1.12.4.js}"></script>
<script type="text/javascript">
    $(function () {
        $.get("/info",function (data) {
            if(data.msg==false){
                alert("您的账号已经在别处登录!");
                location.href="/login";
            }
        })
    })
</script>
</html>

数据库

/*
 Navicat Premium Data Transfer

 Source Server         : 120.77.223.242
 Source Server Type    : MySQL
 Source Server Version : 80018
 Source Host           : 120.77.223.242:3306
 Source Schema         : test

 Target Server Type    : MySQL
 Target Server Version : 80018
 File Encoding         : 65001

 Date: 25/11/2019 16:43:18
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, '何城东', '123');

SET FOREIGN_KEY_CHECKS = 1;

controller层

package com.data.controller;

import com.data.pojo.User;
import com.data.service.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Controller
public class testredis {
    @Autowired
    private UserServiceImpl userService;

    @RequestMapping("/getall")
    @ResponseBody
    public Object getall(){
        return userService.getall();
    }

    @GetMapping(value = "/login")
    public String login1(){
        return  "login";
    }
    @GetMapping(value = "/success")
    public String success(){
        return  "index";
    }

    @PostMapping("/doLogin.html")
    public String login(HttpServletResponse response , HttpServletRequest request, User us, Model model){
        try{
            User u = userService.userlogin(request, response, us);
            if(u==null){
                model.addAttribute("error","用户名或密码不匹配");
                return "login";
            }
            return "redirect:/success";
        }catch (Exception e){
            e.printStackTrace();
            model.addAttribute("error","用户名或密码不匹配");
            return "login";
        }
    }
    @GetMapping("/info")
    @ResponseBody
    public Map getUserInfo(HttpServletResponse response , HttpServletRequest request) throws Exception {
        Map<Object,Object> map=new HashMap<>();
        try{

            String s = userService.getUserByToken(response, request);
            if(s!=null){
                map.put("msg",true);
            }else{
                map.put("msg",false);
            }
            return map;
        }catch (Exception e){
            map.put("success","根据token获取用户信息失败");
            return map;
        }
    }
}

实现效果

在这里插入图片描述
在这里插入图片描述

我们先谷歌浏览器登录一次,再换火狐浏览器登录一下,然后回到谷歌登录成功页面刷新

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值