日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

SpringBoot SSO輕松實現(附demo)

瀏覽:61日期:2023-03-26 18:19:25
前言

網上SSO的框架很多,此篇文章使用的是自寫的SSO來實現簡單的登錄授權功能,目的在于擴展性,權限這方面,自寫擴展性會好點。

提示:以下是本篇文章正文內容,下面案例可供參考

一、技術介紹1.SSO是什么?

單點登錄(SingleSignOn,SSO),就是通過用戶的一次性鑒別登錄。當用戶在身份認證服務器上登錄一次以后,即可獲得訪問單點登錄系統中其他關聯系統和應用軟件的權限,同時這種實現是不需要管理員對用戶的登錄狀態或其他信息進行修改的,這意味著在多個應用系統中,用戶只需一次登錄就可以訪問所有相互信任的應用系統。這種方式減少了由登錄產生的時間消耗,輔助了用戶管理,是目前比較流行的。

二、使用步驟1.引入maven庫

代碼如下(示例):

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.1</version> <relativePath/> </parent> <dependencies> <dependencies> <dependency> <artifactId>hyh-boot-starter-redis</artifactId> <groupId>com.hyh.redis</groupId> <version>1.0.0</version> </dependency> </dependencies>2.具體使用示例

ILogin接口:

package com.hyh.sso;import com.hyh.sso.po.LoginResult;/** * 登錄接口 * * @Author: heyuhua * @Date: 2021/1/8 17:14 */public interface ILogin { /** * 登錄 * * @param account 用戶名 * @param password 密碼 * @param callbackUrl 用戶驗證回調URL * @return */ LoginResult login(String account, String password, String callbackUrl);}

登錄狀態枚舉:

package com.hyh.sso;/** * 登錄狀態枚舉 * * @Author: heyuhua * @Date: 2021/1/8 16:59 */public enum LoginStatus { SUCCESS(1, '登錄成功'), ING(0, '登錄中'), FAIL(-1, '登錄失敗'), ERROR(-2, '登錄異常'), CALLBACK_ERROR(-3, '登錄回調異常'), ACCOUNT_LOCK(-4, '賬戶被鎖定'), EXPIRE(-5,'登錄用戶已過期'); /** * 登錄狀態碼 */ private int code; /** * 登錄狀態消息 */ private String message; private LoginStatus(int code, String message) { this.code = code; this.message = message; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }

登錄類型枚舉:

package com.hyh.sso;/** * 登錄類型 * * @Author: heyuhua * @Date: 2021/1/8 17:16 */public enum LoginTypes { /** * 登入 */ IN, /** * 登出 */ OUT;}

登錄常規接口:

package com.hyh.sso;package com.hyh.sso.service;import com.hyh.sso.ILogin;/** * 常規登錄接口 * * @Author: heyuhua * @Date: 2021/1/8 17:54 */public interface LoginService extends ILogin {}

登錄接口實現:

package com.hyh.sso.service.impl;import com.alibaba.fastjson.JSON;import com.hyh.sso.LoginStatus;import com.hyh.sso.po.LoginResult;import com.hyh.sso.po.LoginUser;import com.hyh.sso.service.LoginService;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.http.HttpEntity;import org.springframework.http.HttpHeaders;import org.springframework.http.MediaType;import org.springframework.stereotype.Service;import org.springframework.web.client.RestTemplate;/** * 登錄接口實現 * * @Author: heyuhua * @Date: 2021/1/8 17:56 */@Servicepublic class LoginServiceImpl implements LoginService { private static final Logger LOG = LoggerFactory.getLogger(LoginServiceImpl.class); /** * rest接口請求模板 */ private static RestTemplate restTemplate = new RestTemplate(); @Override public LoginResult login(String account, String password, String callbackUrl) { LoginResult loginResult = null; try { HttpHeaders headers = new HttpHeaders(); //設置請求媒體數據類型 headers.setContentType(MediaType.APPLICATION_JSON); //設置返回媒體數據類型 headers.add('Accept', MediaType.APPLICATION_JSON.toString()); HttpEntity<String> formEntity = new HttpEntity<String>(JSON.toJSONString(new LoginUser(account, password)), headers); loginResult = restTemplate.postForObject(callbackUrl, formEntity, LoginResult.class); } catch (Exception e) { LOG.error('login valid callback error', e); return new LoginResult(LoginStatus.CALLBACK_ERROR); } return loginResult == null ? new LoginResult(LoginStatus.ERROR) : loginResult; }}

登錄用戶對象:

package com.hyh.sso.po;/** * 登錄用戶對象 * * @Author: heyuhua * @Date: 2021/1/8 16:58 */public class LoginUser { /** * 賬號 */ private String account; /** * 密碼 */ private String password; /** * 登錄時間 */ private String loginTime; public LoginUser(String account, String password) { this.account = account; this.password = password; } public LoginUser() { } public String getAccount() { return account; } public void setAccount(String account) { this.account = account; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getLoginTime() { return loginTime; } public void setLoginTime(String loginTime) { this.loginTime = loginTime; }}

用戶Token對象:

package com.hyh.sso.po;import com.hyh.utils.code.MD5;import com.hyh.utils.common.StringUtils;import java.util.Calendar;/** * 用戶Token對象 * * @Author: heyuhua * @Date: 2021/1/8 17:07 */public class UserToken { /** * token */ private String token; /** * 過期時間 */ private String expireTime; public UserToken(String token, String expireTime) { this.token = token; this.expireTime = expireTime; } public UserToken() { } public static UserToken getUserToken() { Calendar nowTime = Calendar.getInstance(); nowTime.add(Calendar.MINUTE, 30); return new UserToken(MD5.getMD5String(StringUtils.ranStr(32)), String.valueOf(nowTime.getTimeInMillis())); } public String getToken() { return token; } public void setToken(String token) { this.token = token; } public String getExpireTime() { return expireTime; } public void setExpireTime(String expireTime) { this.expireTime = expireTime; } /** * 生成Token */ private String generateToken() { return MD5.getMD5String(StringUtils.ranStr(32)); }}

登錄結果對象:

package com.hyh.sso.po;import com.hyh.sso.LoginStatus;import com.hyh.sso.LoginTypes;/** * 登錄結果對象 * @Author: heyuhua * @Date: 2021/1/8 16:58 */public class LoginResult { /** * 登錄用戶對象 */ private LoginUser loginUser; /** * 登錄用戶令牌 */ private UserToken userToken; /** * 登錄狀態 */ private LoginStatus loginStatus; /** * 登錄類型 */ private LoginTypes loginTypes; public LoginResult(){} public LoginResult(LoginStatus loginStatus) { this.loginStatus = loginStatus; } public LoginUser getLoginUser() { return loginUser; } public void setLoginUser(LoginUser loginUser) { this.loginUser = loginUser; } public UserToken getUserToken() { return userToken; } public void setUserToken(UserToken userToken) { this.userToken = userToken; } public LoginStatus getLoginStatus() { return loginStatus; } public void setLoginStatus(LoginStatus loginStatus) { this.loginStatus = loginStatus; } public LoginTypes getLoginTypes() { return loginTypes; } public void setLoginTypes(LoginTypes loginTypes) { this.loginTypes = loginTypes; } @Override public String toString() { return 'LoginResult{' +'loginUser=' + loginUser +', userToken=' + userToken +', loginStatus=' + loginStatus +', loginTypes=' + loginTypes +’}’; }}

登錄助手:

package com.hyh.sso.helper;import com.alibaba.fastjson.JSON;import com.hyh.redis.helper.RedisHelper;import com.hyh.sso.LoginStatus;import com.hyh.sso.po.LoginResult;import com.hyh.sso.po.LoginUser;import com.hyh.sso.po.UserToken;import com.hyh.sso.service.LoginService;import com.hyh.utils.common.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.util.Assert;import javax.annotation.Resource;import java.util.Date;import java.util.concurrent.TimeUnit;/** * 登錄助手 * * @Author: heyuhua * @Date: 2021/1/8 17:13 */@Componentpublic class LoginHelper { /** * 日志 */ private static final Logger LOG = LoggerFactory.getLogger(LoginHelper.class); /** * 登錄用戶信息KEY */ private final String LOGIN_USER_KEY = 'login:user:'; /** * 登錄用戶TOKEN KEY */ private final String LOGIN_TOKEN_KEY = 'login:token:'; /** * 登錄失敗統計 KEY */ private final String LOGIN_FAIL_COUNT_KEY = 'login:fail:count'; /** * 登錄失敗最多允許次數 */ private final long MAX_FAIL_COUNT = 5; /** * 登錄服務 */ @Resource private LoginService loginService; /** * redis助手 */ @Autowired private RedisHelper redisHelper; /** * 登錄 * * @param account 用戶名 * @param password 密碼 * @param callbackUrl 回調URL * @return */ public LoginResult login(String account, String password, String callbackUrl) { Assert.notNull(account, 'account is null '); Assert.notNull(password, 'password is null '); Assert.notNull(callbackUrl, 'callbackUrl is null '); //判斷賬戶是否多次登錄失敗被鎖定 String value = redisHelper.getStringValue(LOGIN_FAIL_COUNT_KEY + account); if (StringUtils.isNotBlank(value)) { Long loginFailCount = Long.parseLong(value); if (loginFailCount.longValue() >= MAX_FAIL_COUNT) {return new LoginResult(LoginStatus.ACCOUNT_LOCK); } } //登錄操作 LoginResult loginResult = loginService.login(account, password, callbackUrl); switch (loginResult.getLoginStatus()) { case SUCCESS://登錄成功loginSuccess(loginResult);break; case FAIL://登錄失敗loginFail(loginResult);break; case ERROR:loginError(loginResult);//登錄異常break; default:break; } return loginResult; } /** * 注銷 * * @param account * @param token */ public void logout(String account, String token) { Assert.notNull(account, 'account is null '); Assert.notNull(token, 'token is null '); removeKey(account, token); } /** * 注銷 * * @param token */ public void logout(String token) { Assert.notNull(token, 'token is null '); removeKey(token); } /** * 獲取登錄用戶 * * @param token * @return */ public LoginUser getLoginUser(String token) { Assert.notNull(token, 'token is null '); String value = redisHelper.getStringValue(LOGIN_USER_KEY + token); if (StringUtils.isNotBlank(value)) { return JSON.parseObject(value, LoginUser.class); } return null; } /** * 移除 key * * @param account * @param token */ private void removeKey(String account, String token) { redisHelper.del(LOGIN_FAIL_COUNT_KEY + account); redisHelper.del(LOGIN_TOKEN_KEY + account); redisHelper.del(LOGIN_USER_KEY + token); } /** * 移除 Key * * @param token */ private void removeKey(String token) { redisHelper.del(LOGIN_USER_KEY + token); //其余的key到達過期時間自動過期 } /** * 登錄異常 * * @param loginResult */ private void loginError(LoginResult loginResult) { LOG.error('user 【' + loginResult.getLoginUser().getAccount() + '】 login error'); } /** * 登錄失敗操作 * * @param loginResult */ private void loginFail(LoginResult loginResult) { String key = LOGIN_FAIL_COUNT_KEY + loginResult.getLoginUser(); redisHelper.increment(key, 30 * 60 * 1000); } /** * 登錄成功操作 * * @param loginResult */ private void loginSuccess(LoginResult loginResult) { LoginUser loginUser = loginResult.getLoginUser(); loginUser.setLoginTime(String.valueOf(new Date().getTime())); UserToken userToken = UserToken.getUserToken(); redisHelper.set(LOGIN_TOKEN_KEY + loginResult.getLoginUser().getAccount(), JSON.toJSONString(userToken), 30, TimeUnit.MINUTES); redisHelper.set(LOGIN_USER_KEY + userToken.getToken(), JSON.toJSONString(loginUser), 30, TimeUnit.MINUTES); redisHelper.del(LOGIN_FAIL_COUNT_KEY + loginResult.getLoginUser()); }}3.配置文件

代碼如下(示例):

server: port: 8088spring: #redis配置 redis: host: 192.168.6.134 port: 30511 password:4.單元測試

測試代碼如下(示例):

@Autowired private LoginHelper loginHelper; @Test public void testLogin() { //測試時先開啟HyhBootApplication String account = 'hyh'; String password = 'hyh-pwd'; String cllbackUrl = 'http://localhost:8088/hyh/login';//在com.hyh.core.web下可查看 LoginResult loginResult = loginHelper.login(account, password, cllbackUrl); System.out.println('loginResult:' + loginResult.toString()); }//控制層代碼 @RequestMapping(value = 'login', method = RequestMethod.POST) public LoginResult login(@RequestBody LoginUser loginUser) { Assert.notNull(loginUser.getAccount(), 'account is null'); Assert.notNull(loginUser.getPassword(), 'password is null'); LoginResult loginResult = new LoginResult(LoginStatus.SUCCESS); loginResult.setLoginUser(loginUser); //模擬直接返回登錄成功 return loginResult; }總結

是不是感覺很簡單?更多用法請點擊下方查看源碼,關注我帶你揭秘更多高級用法

源碼地址:點此查看源碼.

到此這篇關于SpringBoot SSO輕松實現(附demo)的文章就介紹到這了,更多相關SpringBoot SSO內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
中文字幕人成乱码在线观看| 中文不卡在线| 国产精品主播在线观看| 日韩中文字幕| 日本成人在线视频网站| 日韩免费精品| 国产伦乱精品| 老司机精品视频网| 久久精品一本| 亚洲性色av| 视频一区中文字幕国产| 日本亚洲欧美天堂免费| 国产欧美高清| 91中文字幕精品永久在线| 另类小说一区二区三区| 黄色精品视频| 欧美va天堂在线| 视频精品一区二区| 国产日本精品| 精品久久久久久久| 欧美gv在线| 久久福利一区| 欧美日韩一区二区三区不卡视频| 国产精品天天看天天狠| 国产成人久久精品麻豆二区| 欧美aa一级| 亚洲一区二区毛片| 日本h片久久| 久久97视频| 日韩在线免费| 亚洲黄色在线| 欧美在线黄色| 成人一二三区| 欧美在线亚洲综合一区| 亚洲开心激情| 久久免费国产| 日本伊人午夜精品| 久久女人天堂| 欧美日韩四区| 国产欧美日韩视频在线| 中文字幕高清在线播放| 在线午夜精品| 国产精品美女久久久久久不卡| 国产精品yjizz视频网| 亚洲小说欧美另类婷婷| 日本在线视频一区二区| 粉嫩av一区二区三区四区五区| 亚洲高清毛片| 欧美一区91| 国产v综合v| 日韩精品中文字幕一区二区| 成人精品视频| 在线精品亚洲| 日本黄色精品| 亚洲精品亚洲人成在线观看| 亚洲天堂资源| 日韩精品一区二区三区中文| 国产一区二区三区探花| 欧美专区一区二区三区| 国产精品一区免费在线| 欧美日一区二区| 国产精品115| 国产亚洲综合精品| 久久97久久97精品免视看秋霞| 亚洲精品午夜av福利久久蜜桃| 国产麻豆一区二区三区精品视频| 亚洲激情中文| 男女激情视频一区| 亚洲va中文在线播放免费| 日韩国产一二三区| 伊人久久亚洲美女图片| 成人亚洲一区二区| 欧美欧美黄在线二区| 九九99久久精品在免费线bt| 精品一区毛片| 国产一区二区三区黄网站| 一区二区国产精品| 久久青草久久| 麻豆一区二区三区| 婷婷综合国产| japanese国产精品| 精品免费av| 亚洲aⅴ网站| 99视频在线精品国自产拍免费观看| 精品国产乱码久久久久久樱花| 亚洲日本三级| 在线亚洲成人| 99久久精品费精品国产| 麻豆成人在线观看| 蜜桃av一区二区在线观看| 久久精品青草| 欧美激情国产在线| 国产精品mm| 欧美欧美黄在线二区| 中文字幕一区二区av| 亚洲国产一区二区三区在线播放| 精品国产免费人成网站| 麻豆一区二区在线| 欧美一级二级三级视频| 亚洲影视一区| 亚洲在线成人| 亚洲成人精选| 亚洲天堂久久| 久久精品青草| 最近高清中文在线字幕在线观看1| 国产精品日本一区二区不卡视频 | 久久99偷拍| 日本亚洲视频| 蜜桃视频免费观看一区| 国产亚洲毛片| 久久高清国产| 久久午夜视频| 丝袜亚洲另类欧美| 欧美日韩三区| 亚洲欧美日韩精品一区二区| 日韩午夜av| 亚洲一区免费| 亚洲综合丁香| 麻豆91精品| 亚洲香蕉视频| 婷婷视频一区二区三区| 亚洲日本三级| 欧美日本一区| 麻豆高清免费国产一区| 国产一区二区三区黄网站| 国产一区二区精品福利地址| 国产一区二区三区黄网站 | 亚洲一区二区三区高清不卡| 影音先锋国产精品| 妖精视频成人观看www| 99亚洲视频| 亚洲免费福利一区| 欧美精品国产| 精品一区电影| 蜜桃精品在线| 激情综合在线| 国产精品久久久亚洲一区| 老牛国内精品亚洲成av人片| 成人在线黄色| 欧美亚洲国产一区| 亚洲色诱最新| 日本不卡高清视频| 欧美激情视频一区二区三区免费 | 麻豆传媒一区二区三区| 成午夜精品一区二区三区软件| 日韩电影在线视频| 免费久久精品| 亚洲精品看片| 国产精品久久久久久模特| 久久永久免费| 99精品小视频| 中文字幕日本一区| 国产精品一区二区美女视频免费看| 麻豆久久一区二区| 日韩在线高清| 美日韩精品视频| 日本少妇精品亚洲第一区| 精品一区二区三区在线观看视频| 久久精品在线| 日韩综合一区二区三区| 激情综合五月| 亚洲欧美视频| 国产精品久久久久久久久久白浆| 极品av在线| 蜜桃视频一区二区| 精品视频在线一区二区在线| 国产h片在线观看| 亚洲一区二区三区四区五区午夜| 欧美午夜网站| 99久久精品网| 日韩不卡一区二区| 国产美女高潮在线观看| 亚洲专区一区| 精品国产一区二区三区av片| 一区免费视频| 久久99久久人婷婷精品综合| 亚洲二区视频| 国产丝袜一区| 国产一区日韩欧美| 欧美一区免费| 国产一区观看| 久久99影视| 先锋影音国产一区| 久久亚洲精品中文字幕| 国产精品嫩草99av在线| 精品国产一区二| 在线午夜精品| 国产一区二区精品久| 免费欧美在线视频| 9999国产精品| 日韩高清不卡在线| 日韩精品麻豆| 欧美日一区二区三区在线观看国产免 | 欧美精品中文| av亚洲在线观看| 成午夜精品一区二区三区软件| 亚洲精品乱码日韩| 在线成人动漫av| 麻豆免费精品视频| 亚洲欧洲美洲国产香蕉|