日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

SpringBoot SSO整合

發(fā)布時間:2023/12/8 javascript 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpringBoot SSO整合 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

SpringBoot系列-SSO整合

  • SpringBoot整合SSO教程
  • 前言
  • 一、技術介紹
    • 1.SSO是什么?
  • 二、使用步驟
    • 1.引入maven庫
    • 2.具體使用示例
    • 3.配置文件
    • 4.單元測試
  • 總結

SpringBoot整合SSO教程

提示:如有疑問請私信聯(lián)系、下方有源代碼地址,請自行拿取


前言

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


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

一、技術介紹

1.SSO是什么?

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

二、使用步驟

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);}

登錄狀態(tài)枚舉:

package com.hyh.sso;/*** 登錄狀態(tài)枚舉** @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,"登錄用戶已過期");/*** 登錄狀態(tài)碼*/private int code;/*** 登錄狀態(tài)消息*/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;}

登錄常規(guī)接口:

package com.hyh.sso;package com.hyh.sso.service;import com.hyh.sso.ILogin;/*** 常規(guī)登錄接口** @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*/ @Service public class LoginServiceImpl implements LoginService {private static final Logger LOG = LoggerFactory.getLogger(LoginServiceImpl.class);/*** rest接口請求模板*/private static RestTemplate restTemplate = new RestTemplate();@Overridepublic 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;/*** 登錄狀態(tài)*/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;}@Overridepublic 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*/ @Component public 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:";/*** 登錄失敗統(tǒng)計 KEY*/private final String LOGIN_FAIL_COUNT_KEY = "login:fail:count";/*** 登錄失敗最多允許次數*/private final long MAX_FAIL_COUNT = 5;/*** 登錄服務*/@Resourceprivate LoginService loginService;/*** redis助手*/@Autowiredprivate 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.134port: 30511password:

4.單元測試

測試代碼如下(示例):

@Autowiredprivate LoginHelper loginHelper;@Testpublic void testLogin() {//測試時先開啟HyhBootApplicationString 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;}

總結

是不是感覺很簡單?更多用法請點擊下方查看源碼,關注我?guī)憬颐馗喔呒売梅?/font>

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

總結

以上是生活随笔為你收集整理的SpringBoot SSO整合的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。