SSO(單點登入)MD5加鹽 原理案例教程 火推
SSO(單點登入)後期用redis儲存
user伺服器放到tokenManager 儲存tonken
原始碼下載:https://gitee.com/qq1350048638/lj_user_server
重點的幾個類程式碼展示出來
前端login.jsp 登入時 通過session儲存tonken
$.ajax({
url:"http://localhost:8881/user/token",
type:"post",
data:{"name":username,"password":password},
dataType:"json",
success:function(result){
if(result.status==1){//成功
sessionStorage.token = result.data.token;//獲取令牌值
window.parent.location.reload();//重新整理當前頁
}else if(result.status==2){//使用者錯
$("#username_error").html(result.msg);
}else if(result.status==3){//密碼錯
$("#password_error").html(result.msg);
}
}
});
UserServer 工程裡面結構
.user.controller類
package com.lj.ovls.user.controller;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.lj.ovls.common.entity.ResponseResult;
import com.lj.ovls.user.service.UserService;
@RestController
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value="/user/token",method=RequestMethod.POST)
public ResponseResult createToken(String name,String password,HttpSession session){
ResponseResult result =
userService.createToken(name, password);
// if(result.getStatus()==1){//成功,才會有token值
// //將token存入session
// Map<String, Object> data = (Map)result.getData();
// session.setAttribute("token",data.get("token"));
// }
return result;
}
@RequestMapping(value="/user/token",method=RequestMethod.GET)
public ResponseResult checkToken(String token){
ResponseResult result =
userService.checkToken(token);
return result;
}
}
Token實體類
public class Token {
private int userId;//登入使用者名稱
private Date expired; //過期時間
private Date lastOperate; // 最近一次操作的時間
...省略get set
}
UserServiceImpl類
將使用者密碼加鹽後和資料庫密碼進行比較
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserMapper userDao;
@Autowired
private TokenManager tokenManager;
@Override
public ResponseResult createToken(
String name, String password) {
ResponseResult result = new ResponseResult();
//檢查賬號和密碼正確性
User user = userDao.selectByName(name);
if(user == null){
result.setStatus(2);
result.setMsg("使用者不存在");
return result;
}
//檢測密碼
//將使用者輸入密碼+salt進行md5處理
String md5Password = Md5Utils.md5(password+user.getSalt());
if(!user.getPassword().equals(md5Password)){
result.setStatus(3);
result.setMsg("密碼不正確");
return result;
}
//賬號和通過檢測
result.setStatus(1);
result.setMsg("登入成功");
//生成一個token
String token = TokenUtil.generatorToken(user.getId());
tokenManager.addToken(token, user.getId());
Map<String, Object> data = new HashMap<String, Object>();
data.put("token", token);
result.setData(data);
return result;
}
@Override
public ResponseResult checkToken(String token) {
ResponseResult result = new ResponseResult();
boolean ok = tokenManager.validate(token);
if(ok){//token通過驗證
result.setStatus(1);
result.setMsg("token令牌合法");
//將最後一次操作時間更新下
tokenManager.updateLastOperate(token);
}else{
result.setStatus(2);
result.setMsg("token令牌不合法");
}
return result;
}
}
Md5加密工具類
public class Md5Utils {
public static byte[] md5(byte[] data) {
try {
MessageDigest md = MessageDigest.getInstance("md5");
md.update(data);
return md.digest();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return new byte[] {};
}
public static String md5(String data) {
try {
byte[] md5 = md5(data.getBytes("utf-8"));
return toHexString(md5);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return "";
}
}
public static String toHexString(byte[] md5) {
StringBuilder buf = new StringBuilder();
for (byte b : md5) {
buf.append(leftPad(Integer.toHexString(b & 0xff), '0', 2));
}
return buf.toString();
}
public static String leftPad(String hex, char c, int size) {
char[] cs = new char[size];
Arrays.fill(cs, c);
System.arraycopy(hex.toCharArray(), 0, cs, cs.length - hex.length(),
hex.length());
return new String(cs);
}
/**
* test
* @param args
*/
public static void main(String[] args) {
System.out.println(md5("1234561296cd20"));
}
}
TokenManager類
@Component
public class TokenManager {
//令牌儲存結構 ConcurrentHashMap
public Map<String, Token> tokenMap =
new ConcurrentHashMap<String, Token>();
/**
* 令牌有效性驗證
* @param stoken 使用者令牌
* @return true有效;false失效
*/
public boolean validate(String stoken) {
System.out.println("Token驗證");
if(tokenMap.containsKey(stoken)){ //令牌存在
Token token = tokenMap.get(stoken);
Date expired = token.getExpired();
Date now = new Date();
if(now.compareTo(expired) > 0){//已過期
tokenMap.remove(stoken);//移除
}else{//未過期
return true;
}
}
return false;
}
/**
* 使用者授權成功後存入授權資訊
* @param stoken 使用者令牌
* @param userId 使用者ID
*/
public void addToken(String stoken, int userId) {
Token token = new Token();
token.setUserId(userId);
token.setLastOperate(new Date());
token.setExpired(new Date(token.getLastOperate().getTime() + 2 * 60 * 1000));
tokenMap.put(stoken, token);
}
/**
* 更新token最近一次操作的時間和有效期期
* @param stoken 使用者令牌
*/
public void updateLastOperate(String stoken) {
Token token = tokenMap.get(stoken);
token.setLastOperate(new Date());
token.setExpired(new Date(token.getLastOperate().getTime() + 2 * 60 * 1000));
}
}
TokenManagerTask類
/**
* 定期清除token列表中過期的令牌
* @author Administrator
*
*/
@Component
@EnableScheduling
public class TokenManagerTask {
@Autowired
private TokenManager tokenManager;
@Scheduled(cron="1/5 * * * * ?")
public void manager(){
// System.out.println("定時清除過期令牌");
Map<String, Token> tokenMap = tokenManager.tokenMap;
for(Entry<String, Token> entiy : tokenMap.entrySet()) {
String stoken = entiy.getKey();
Token token = entiy.getValue();
Date expired = token.getExpired();
Date now = new Date();
// System.out.println("token列表:"+stoken+" 有效期:"+expired+" 授權時間:"+token.getLastOperate());
//當前時間大於過期時間,說明標識已經過期時間,將token移除
if(now.compareTo(expired) > 0) {
//已過期,清除
tokenMap.remove(stoken);
// System.out.println("清除了:"+stoken+" 清除時間:"+now);
}
}
}
}
TokenUtil 類
public class TokenUtil {
/**
* 生成一個令牌號
* @return 令牌號
*/
public static String generatorToken(int userId){
UUID uuid = UUID.randomUUID();
return uuid.toString()+"-"+userId;
}
public static void main(String[] args){
System.out.println(generatorToken(12));
}
}
另外一個工程裡面進行驗證
paper工程
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class InterceptorsConfig extends WebMvcConfigurerAdapter{
@Autowired
private CheckLoginInterceptor checkLogin;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(checkLogin).addPathPatterns("/paper/subject/*");
}
}
paper類
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import ovls.common.entity.ResponseResult;
import ovls.paper.remote.UserServiceRemote;
@Component
public class CheckLoginInterceptor implements HandlerInterceptor{
// @Autowired
// private RestTemplateBuilder restBuilder;
// @Autowired
// private RestTemplate restTemplate;
@Autowired
private UserServiceRemote userRemote;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//獲取請求帶過來的token
String token = request.getParameter("token");
System.out.println("呼叫/user/token服務檢查token是否合法"+token);
response.setContentType("application/json;charset=UTF-8");
if(token != null && !"".equals(token)){
//呼叫/user/token服務檢查token是否合法,合法就返回true,不合法返回false
// RestTemplate restTemplate = restBuilder.build();
//呼叫ovls_course_server的服務查詢所有學科資訊
// ResponseResult userResult = restTemplate.getForObject(
// "http://USERSERVER/user/token?token="+token, ResponseResult.class);
//利用Feign介面呼叫服務
ResponseResult userResult = userRemote.checkToken(token);
if(userResult.getStatus()==1){//通過驗證,表示token合法
return true;
}
}
//未通過驗證
PrintWriter out = response.getWriter();
out.println("{\"stauts\":2,\"msg\":\"不合法使用者\"}");
out.close();
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
}
}
相關文章
- 單點登入 SSO 的實現原理
- 初探單點登入 SSO
- SSO單點登入邏輯
- CAS實現單點登入SSO執行原理探究
- CAS單點登入(SSO)實戰(一)
- Casdoor + OAuth 實現單點登入 SSOOAuth
- CAS SSO單點登入框架學習框架
- 一箇中介軟體加幾行程式碼搞定 SSO 單點登入行程
- 推薦一個分散式單點登入框架XXL-SSO!分散式框架
- 單點登入原理
- 最強SSO單點登入教程(三)單點登出流程分析
- OAuth2實現單點登入SSOOAuth
- 【SSO】--單點登入之過濾器(filter)過濾器Filter
- java實現MD5加鹽加密方法Java加密
- CAS實現單點登入SSO執行原理探究(終於明白了)
- 記一次 SSO 單點登入實現
- 單點登入SSO和Oauth2.0 文章3OAuth
- [精華][推薦]CAS SSO單點登入服務端客戶端例項服務端客戶端
- 推薦:J2EE中使用者授權和SSO(單點登入)
- CAS SSO單點登入服務端環境搭建服務端
- CAS SSO單點登入客戶端環境搭建客戶端
- 實戰模擬│單點登入 SSO 的實現
- 談談SSO單點登入的設計實現
- 【SSO】--實現單點登入研究過程總結
- 基於IdentityServer4的OIDC實現單點登入(SSO)原理簡析IDEServer
- SSO單點登入最全詳解(圖文全面總結)
- 單點登入原理與簡單實現
- 不務正業的前端之SSO(單點登入)實踐前端
- 3.CAS SSO單點登入客戶端環境搭建客戶端
- 整合spring cloud雲架構 - SSO單點登入之OAuth2.0登入認證SpringCloud架構OAuth
- Spring Cloud雲架構 - SSO單點登入之OAuth2.0登入認證(1)SpringCloud架構OAuth
- 對SSO單點登入和OAuth2.0的區別和理解OAuth
- spring cloud微服務分散式雲架構-單點登入(SSO)SpringCloud微服務分散式架構
- Spring+ Spring cloud + SSO單點登入應用認證SpringCloud
- 完全跨域的單點登入(SSO)解決方案原始碼解析跨域原始碼
- spring+springmvc+Interceptor+jwt+redis實現sso單點登入SpringMVCJWTRedis
- SSO單點登入三種情況的實現方式詳解
- 整合spring cloud雲架構 - SSO單點登入之OAuth2.0登入認證(1)SpringCloud架構OAuth