SpringBoot+Vue+Redis實(shí)現(xiàn)單點(diǎn)登錄(一處登錄另一處退出登錄)
一、需求
實(shí)現(xiàn)用戶在瀏覽器登錄后,跳轉(zhuǎn)到其他頁(yè)面,當(dāng)用戶在其它地方又登錄時(shí),前面用戶登錄的頁(yè)面退出登錄(列如qq擠號(hào)那種方式)
二、實(shí)現(xiàn)思路
用戶在前端填寫用戶信息登錄后,后臺(tái)接收數(shù)據(jù)先去數(shù)據(jù)庫(kù)進(jìn)行判斷,如果登錄成功,創(chuàng)建map集合,以用戶id為鍵,token為值,先通過當(dāng)前登錄用戶的id去獲取token,如果token存在說明該用戶已經(jīng)登錄過,調(diào)用redis以token為鍵刪除上個(gè)用戶的信息,調(diào)用方法生成新token,并將token存入map集合,將用戶信息存入redis,并將token存入cookie。當(dāng)用戶回到前面登錄的頁(yè)面時(shí),刷新頁(yè)面,調(diào)用方法,通過后端獲取cookie的token值,通過token在redis中查詢用戶信息是否存在,如果不存在,前端通過返回值判斷重新回到登錄頁(yè)面!
三、實(shí)現(xiàn)代碼
后端:
1、創(chuàng)建SpringBoot項(xiàng)目,創(chuàng)建User表,由于是通過Vue編寫的,所以是前后端分離,需要跨域,我這里編寫了跨域配置類,還有redis的util類,返回的封裝類,cookie的util類,文末有源碼提供,可以自行提取。
2、yum配置文件
spring:
redis:
database: 0 #redis的默認(rèn)數(shù)據(jù)庫(kù)為0
host: 127.0.0.1 #鏈接redis的ip
port: 6379 #鏈接redis的端口號(hào)
password: #鏈接redis的密碼 默認(rèn)為空
jedis:
pool:
max-total: 200 #鏈接redis的總數(shù)目
max-active: 100 #鏈接redis的最大
max-idle: 8 #最大的鏈接數(shù)量
min-idle: 5 #最小的鏈接數(shù)量
datasource:
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
jpa:
show-sql: true
server:
port: 8888
REDIS_KEY : USER_TOKEN
3、編寫實(shí)體User.class
@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;
}
4、編寫Dao,UserDao.class
public interface UserDao extends JpaRepository<User,Integer> {
public User findByUsernameAndPassword(String username, String password);
}
5、編寫serviceImpl,UserServiceImpl.class進(jìn)行登錄的業(yè)務(wù)邏輯處理
@Service
public class UserServiceImpl{
@Autowired
private UserDao userDao;
@Autowired
private JedisDao jedisDao;
@Value("${REDIS_KEY}") //從配置文件中取值
private String KEY;
private Map<Integer,String> UserLogin = new HashMap<>();
/**
* 登錄
* @param request
* @param response
* @param u
* @return
*/
public User userlogin(HttpServletRequest request, HttpServletResponse response, User u){
//查詢登錄是否成功
User user=userDao.findByUsernameAndPassword(u.getUsername(),u.getPassword());
//判斷us是否為空
if(user==null){
return null;
}
//生成token
String token="user_"+ UUID.randomUUID().toString();
//從map中獲得redis中的key
String oldToken = UserLogin.get(user.getId());
//判斷map中是否存在該id
if(!StringUtils.isEmpty(oldToken)){
//刪除redis中老的值
jedisDao.delValue(oldToken);
}
//將新的的key保存到map中
UserLogin.put(user.getId(),token);
//將信息存入redis
jedisDao.setValue(token, JsonUtils.objectToJson(user));
//將token放入cookie中
CookieUtils.setCookie(request,response,KEY,token,5*60,true);
return user;
}
/**
* 判斷是否登錄
* @param response
* @param request
* @return
*/
public String getUserByToken(HttpServletResponse response, HttpServletRequest request) {
//從cookie中取出用戶token
String token=CookieUtils.getCookieValue(request,KEY);
//從redis中取出用戶信息
String user= jedisDao.getValue(token);
return user;
}
}
6、編寫controller,接收前端請(qǐng)求,返回?cái)?shù)據(jù)
@RestController
public class LoginController {
@Autowired
private UserServiceImpl userService;
/**
* 登錄
* @param response
* @param request
* @param user
* @param model
* @return
*/
@PostMapping("/login")
public ResponseResult Login(HttpServletResponse response , HttpServletRequest request, @RequestBody User user, Model model){
ResponseResult responseResult=new ResponseResult();
try {
User user2 = userService.userlogin(request, response, user);
if (user2!=null){
responseResult.setState(200);
responseResult.setMsg("登錄成功!");
return responseResult;
}else{
responseResult.setState(202);
responseResult.setMsg("用戶名或密碼錯(cuò)誤!");
return responseResult;
}
}catch (Exception e) {
responseResult.setState(500);
responseResult.setMsg("發(fā)生錯(cuò)誤,登錄失?。?);
return responseResult;
}
}
/**
* 判斷是否登錄
* @param response
* @param request
* @return
* @throws Exception
*/
@GetMapping("/toLogin")
public ResponseResult getUserInfo(HttpServletResponse response , HttpServletRequest request) throws Exception {
ResponseResult responseResult=new ResponseResult();
try{
String token = userService.getUserByToken(response, request);
if(token!=null){
responseResult.setState(200);
responseResult.setMsg("登錄中!");
return responseResult;
}else{
responseResult.setState(202);
responseResult.setMsg("在別處登錄!");
return responseResult;
}
}catch (Exception e){
response.setStatus(500);
responseResult.setMsg("發(fā)生錯(cuò)誤!");
return responseResult;
}
}
}
Vue前端
1、創(chuàng)建Vue項(xiàng)目:vue init webpack 項(xiàng)目名稱
2、引入axios:npm install --save axios vue-axios
3、引入element:npm i element-ui -S
4、在src的main.js下配置
import axios from 'axios' import VueAxios from 'vue-axios' // element-ui 引入文件 import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' //注冊(cè) VueAxios, axios Vue.use(VueAxios, axios) Vue.use(ElementUI) //配置axios支持cookie axios.defaults.withCredentials = true;
5、在src的components下創(chuàng)建login.vue,userinfo.vue,并在src的router下配置訪問地址
import Vue from 'vue'
import Router from 'vue-router'
import login from '@/components/login'
import UserInfo from '@/components/userinfo'
Vue.use(Router)
export default new Router({
routes: [{
path: '/login',
component: login
}, {
path: '/user_info',
component: UserInfo
}]
})
6、前端的代碼這里就不貼出了,代碼是有詳細(xì)的注釋,請(qǐng)自行下載代碼查看
四、代碼地址和演示效果
登錄:


下線:

dome代碼地址
鏈接: https://pan.baidu.com/s/1rXU46LCLpMxDzVEV_CpqFw
提取碼: yquh
總結(jié)
以上所述是小編給大家介紹的SpringBoot+Vue+Redis實(shí)現(xiàn)單點(diǎn)登錄(一處登錄另一處退出登錄),希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
- springboot簡(jiǎn)單實(shí)現(xiàn)單點(diǎn)登錄的示例代碼
- springboot oauth2實(shí)現(xiàn)單點(diǎn)登錄實(shí)例
- springboot 集成cas5.3 實(shí)現(xiàn)sso單點(diǎn)登錄詳細(xì)流程
- springboot集成CAS實(shí)現(xiàn)單點(diǎn)登錄的示例代碼
- SpringBoot整合SSO(single sign on)單點(diǎn)登錄
- 使用springboot結(jié)合vue實(shí)現(xiàn)sso單點(diǎn)登錄
- 基于springboot和redis實(shí)現(xiàn)單點(diǎn)登錄
- 單點(diǎn)登錄的概念及SpringBoot實(shí)現(xiàn)單點(diǎn)登錄的操作方法
相關(guān)文章
Java面試題沖刺第二十八天--數(shù)據(jù)庫(kù)(5)
這篇文章主要為大家分享了最有價(jià)值的三道關(guān)于數(shù)據(jù)庫(kù)的面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下2021-09-09
Spring手動(dòng)生成web.xml配置文件過程詳解
這篇文章主要介紹了Spring手動(dòng)生成web.xml配置文件過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
java 關(guān)鍵字static詳細(xì)介紹及如何使用
這篇文章主要介紹了java 關(guān)鍵字static詳細(xì)介紹及如何使用的相關(guān)資料,需要的朋友可以參考下2017-03-03
JdbcTemplate方法介紹與增刪改查操作實(shí)現(xiàn)
這篇文章主要給大家介紹了關(guān)于JdbcTemplate方法與增刪改查操作實(shí)現(xiàn)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用JdbcTemplate具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
Java實(shí)現(xiàn)一個(gè)簡(jiǎn)易聊天室流程
這篇文章主要介紹了我的java課程設(shè)計(jì)一個(gè)多人聊天室(socket+多線程)本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-11-11
python中jieba庫(kù)(中文分詞庫(kù))使用安裝教程
這篇文章主要介紹了python中jieba庫(kù)(中文分詞庫(kù))使用安裝教程,jieba庫(kù)是通過中文詞庫(kù)的方式來識(shí)別分詞的。它首先利用一個(gè)中文詞庫(kù),通過詞庫(kù)計(jì)算漢字之間構(gòu)成詞語(yǔ)的關(guān)聯(lián)概率,所以通過計(jì)算漢字之間的概率,就可以形成分詞的結(jié)果,需要的朋友可以參考下2023-04-04
java數(shù)據(jù)結(jié)構(gòu)關(guān)于棧的實(shí)例應(yīng)用
大家好,本篇文章主要講的是java數(shù)據(jù)結(jié)構(gòu)關(guān)于棧的實(shí)例應(yīng)用,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12
Java實(shí)戰(zhàn)之實(shí)現(xiàn)物流配送系統(tǒng)示例詳解
這篇文章主要介紹了一個(gè)java實(shí)戰(zhàn)項(xiàng)目:通過java、SSM、JSP、mysql和redis實(shí)現(xiàn)一個(gè)物流配送系統(tǒng)。文中的示例代碼非常詳細(xì),需要的朋友可以參考一下2021-12-12

