当前位置:网站首页>Single sign on logic
Single sign on logic
2022-06-26 09:28:00 【Great white bear_ BlankBear】
When the user logs in, they will sessionid Pass in , Record to database
Add an interface to get users ID( only ) Corresponding sessionID
Call this interface to determine the current... When you jump or refresh the page later sessionID And stored in the database sessionID Is it the same . Not the same jump to the login page , Log back in . Yes, you can enter the interface
Another kind of logic is to only do it on the back end , Refer to the following link
Knowledge point
Ideas as follows :

demonstration
Concrete realization :
1. Maintain a map aggregate
public class LoginUserMap {
private static Map<String, String> loginUserMap = new ConcurrentHashMap<String, String>();
/**
* set Method
*
* @param loginId User unique identification , User name or user Id
* @param sessionId sessionId
*/
public static void setLoginUserMap(String loginId, String sessionId) {
loginUserMap.put(loginId, sessionId);
}
/**
* get Method
*
* @return
*/
public static Map<String, String> getLoginUserMap() {
return loginUserMap;
}
/**
* according to sessionId remove map The value in
*
* @param sessionId
*/
public static void removeUser(String sessionId) {
for (Map.Entry<String, String> entry : loginUserMap.entrySet()) {
if (sessionId.equals(entry.getValue())) {
loginUserMap.remove(entry.getKey());
break;
}
}
}
/**
* Determine whether the user is map in
*
* @param loginId
* @param sessionId
* @return
*/
public static boolean isInLoginUsers(String loginId, String sessionId) {
return (loginUserMap.containsKey(loginId) && sessionId.equals(loginUserMap.get(loginId)));
}
2. Achieve one session monitor ,session Destruction can be updated in time map
@WebListener
public class SessionListener implements HttpSessionListener {
private Logger logger=LoggerFactory.getLogger(SessionListener.class);
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
String sessionId = session.getId();
//session Eliminate when destroyed loginUserMap Medium sessionId
LoginUserMap.removeUser(sessionId);
logger.info("session The destruction ,sessionId:"+sessionId);
}
}
3. Define filters , You can customize a filter , But exclude login requests ( A little ), The core code is as follows
// Determine whether to log in repeatedly
String loginName = username.getLoginName();// Get the user's unique identity
// Judge the current user session Whether to change
if (!LoginUserMap.isInLoginUsers(loginName,session.getId())) {
// Define your own implementation , Being pushed off the line , My is :
//session Send changes , Means to log in elsewhere
// Being pushed off the line , eliminate session, Prompt information , Realize jump
request.setAttribute("online",false);
request.getRequestDispatcher("/logout.do").forward(request,response);
return;
}
chain.doFilter(new XssHttpSerlet((HttpServletRequest) request), response);
4. Register listeners and filters
<filter>
<filter-name>LoginLimitFilter</filter-name>
<filter-class>io.github.brightloong.loginlimite.LoginLimitFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoginLimitFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
in addition , You can set the polling method to judge , Let users log off in time , But it consumes resources , I take the method of requesting a failed jump , Directly call the login exit interface
summary
The implementation cannot solve the problem of multiple logins in the same browser , And sessionId identical , But it can realize the basic operation of restricting login , Because what we do is kick off the line , So compared with online accounts , Unable to log in , Slightly simpler , If you do the second form , You need to consider session Whether to eliminate the problem
There is also a reference to the following link
https://brightloong.github.io/2017/03/08/Java-Web%E4%B9%8B%E9%99%90%E5%88%B6%E7%94%A8%E6%88%B7%E7%99%BB%E5%BD%95%E5%A4%9A%E5%A4%84%E7%99%BB%E5%BD%95/#more
Recently I met a requirement in the project , It is required to restrict a single user from logging in to multiple terminals ( Let's say the user A Login at , And then in B Login at , here A Should be squeezed off the line ). At first I wanted to use spring Of security Directly through configuration , Simple and convenient . But it's a pity , The project I have done uses the framework encapsulated by the company , Still in use sprign2.X. ok , Since this method doesn't work , Then I will write the code to realize it honestly , There are many ways to realize it on the Internet , Baidu 、 Google has gone through a wave , Much more decisive , But in the past, I felt the same . There is also what to use application ah ,session What? . Last , I'll do it myself , Get plenty of food and clothing . First of all, let me talk about my ideas :
Use a whole picture Map Used to save when logging in sessionId,Map Of key For login ,value by sessionID, Because it was the later ones who crowded out the front ones , So don't judge , Directly covered Map The value in is OK.
Achieve one HttpSessionListener, stay session The destruction ( such as session Be overdue ) When it comes to cleaning up Map Corresponding value in .
Achieve one Filter, Used to intercept requests , Judge to use the current sessionId Whether in Map in , If you are not performing an exit operation .
Used to save the logged in user SessionID Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | public class LoginUserMap {
private static Map<String, String> loginUsers = new ConcurrentHashMap<String, String>();
/**
* Put users and sessionId Deposit in map
* @param key
* @param value
*/
public static void setLoginUsers(String loginId, String sessionId) {
loginUsers.put(loginId, sessionId);
}
/**
* obtain loginUsers
* @return
*/
public static Map<String, String> getLoginUsers() {
return loginUsers;
}
/**
* according to sessionId remove map The value in
* @param sessionId
*/
public static void removeUser(String sessionId) {
for (Map.Entry<String, String> entry : loginUsers.entrySet()) {
if (sessionId.equals(entry.getValue())) {
loginUsers.remove(entry.getKey());
break;
}
}
}
/**
* Determine whether the user is loginusers in
* @param loginId
* @param sessionId
* @return
*/
public static boolean isInLoginUsers(String loginId, String sessionId) {
return (loginUsers.containsKey(loginId) && sessionId.equals(loginUsers.get(loginId)));
}
}
|
Save in the login method sessionID
Here I will not give a specific implementation , After all, different projects are different , I'll write a general step , Help you understand :
1 2 3 4 5 6 7 8 9 10 | // Where the login method is located
public void login(ttpServletRequest request) {
try {
......// A series of login methods
HttpSession session = request.getSession();
LoginUserMap.setLoginUsers(username, session.getId());// preservation sessionId To map in
} catch (LoginException ex) {
throw ex;
}
}
|
Realization HttpSessionListener
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class SessionListener implements HttpSessionListener {
private Log log = LogFactory.getLog(SessionListener.class);
/**
* establish session When the action
* @param event
*/
@Override
public void sessionCreated(HttpSessionEvent event) {
}
/**
* The destruction session When the action
* @param event
*/
@Override
public void sessionDestroyed(HttpSessionEvent event) {
HttpSession session = event.getSession();
String sessionId = session.getId();
// remove loginUsers Have been destroyed in session
LoginUserMap.removeUser(sessionId);
log.info(sessionId + " Be destroyed !");
}
}
|
xml The configuration is as follows :
1 2 3 | <listener> <listener-class>io.github.brightloong.loginlimite.SessionListener</listener-class> </listener> |
Filter Realization
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | public class LoginLimitFilter implements Filter{
private Log log = LogFactory.getLog(LoginLimitFilter.class);
/**
* Method of destruction
*/
@Override
public void destroy() {
}
/**
* Filtering requests
* @param request
* @param response
* @param filterChain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest servletRequest = (HttpServletRequest) request;
HttpServletResponse servletResponse = (HttpServletResponse) response;
HttpSession session = servletRequest.getSession();
// Get project path
String path = servletRequest.getContextPath();
String basePath = servletRequest.getScheme()+"://"+servletRequest.getServerName()+":"+servletRequest.getServerPort()+path;
try {
// Get user information , If not, an error will be thrown , This is my way , The delegate user has not logged in yet
IUser user = UserUtils.getCurrUserInfo();
String loginId = user.getLoginId();
// Judge the current user's sessionId Whether in loginUsers in , If not implemented if Post operation
if(!LoginUserMap.isInLoginUsers(loginId, session.getId())) {
// The current user logout
logout();// Their own logout Method
// Transfer to the login page , It also indicates that the exit mode is extrusion
servletResponse.sendRedirect(basePath + "?logoutway=edge");
}
} catch (Exception e) {
log.debug(" Failed to get current user information , The user is not logged in !", e);
} finally {
filterChain.doFilter(request, response);
}
}
/**
* Initialization method
* @param arg0
* @throws ServletException
*/
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
|
xml The configuration is as follows :
1 2 3 4 5 6 7 8 | <filter> <filter-name>LoginLimitFilter</filter-name> <filter-class>io.github.brightloong.loginlimite.LoginLimitFilter</filter-class> </filter> <filter-mapping> <filter-name>LoginLimitFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> |
Display prompt message
When the user clicks, it will trigger filter To monitor , If it is detected that you have logged in , Will go to the login page , At this time, it is necessary to judge whether it is pushed down , I use it here layer Prompt box .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | window.onload = function(){
if(window.parent != window){
window.parent.location.href=window.location.href;
} else {
if(GetQueryString('logoutway')) {
//alert(' The user is already logged in elsewhere , You are offline ');
layer.alert(' This account is already logged in elsewhere , You have been forced to go offline , If it is not your own operation, please log in again and change your password in time ', {
skin: 'layui-layer-lan', // Style class name
title: ' Tips '
,closeBtn: 0
}, function(){
var url = window.location.href;
window.location.href = url.substr(0,url.indexOf('?logoutway=edge'));
});
}
}
}
function GetQueryString(name)
{
var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if(r!=null)return unescape(r[2]); return null;
} |
边栏推荐
- install ompl.sh
- Solutions for safety management and control at the operation site
- 《一周搞定模电》—电源电路
- 0 basic how to make a cool leadership cockpit?
- GAN Inversion: A Survey
- 深度学习(初识tensorflow2.版本)之三好学生成绩问题(1)
- PHP does not allow images to be uploaded together with data (no longer uploading images before uploading data)
- Statistics of various target quantities of annotations (XML annotation format)
- JSON file to XML file
- pcl install
猜你喜欢

The shutter tabbar listener is called twice

Error importerror: numpy core. multiarray failed to import

工企专利匹配数据(数十万数据量)1998-2014年

"One week's data collection" -- combinational logic circuit
![[Journal of Computer Aided Design & computer graphics] overview of research on pedestrian re recognition methods based on generated countermeasure network](/img/a9/1361df052f0474e5c50b948a92c42a.jpg)
[Journal of Computer Aided Design & computer graphics] overview of research on pedestrian re recognition methods based on generated countermeasure network

There is a strong demand for enterprise level data integration services. How to find a breakthrough for optimization?
![Modify coco evaluation index maxdets=[10,15,20]](/img/f6/a0fbf601371aa51ec5b0136574c756.jpg)
Modify coco evaluation index maxdets=[10,15,20]

Merrill Lynch data tempoai is new!

"One week's work on Analog Electronics" - diodes

Classified catalogue of high quality sci-tech periodicals in the field of computing
随机推荐
《一周搞定数电》——组合逻辑电路
Creation and use of XSync synchronization script (taking debian10 cluster as an example)
Curriculum learning (CL)
Comprehensive interpretation! Use of generics in golang
Solve Django's if Version (1, 3, 3): raise improverlyconfigured ('mysqlclient 1.3.3 or new is required
Self taught neural network series - 1 Basic programming knowledge
安装 新版本cmake & swig & tinyspline
"One week's work on Analog Electronics" - optocoupler and other components
jz2440---使用uboot烧录程序
Self taught neural network series - 4 learning of neural network
Pycharm [debug] process stuck
《一周搞定模电》—55定时器
Self taught programming series - 4 numpy arrays
【CVPR 2021】Unsupervised Pre-training for Person Re-identification(UPT)
Construction practice of bank intelligent analysis and decision-making platform
Is it safe to dig up money and make new debts
2021年全国职业院校技能大赛(中职组)网络安全竞赛试题(1)详细解析教程
【pulsar学习】pulsar架构原理
OpenCV depthframe -> pointcloud 导致 segmentation fault!
"One week to solve the model electricity" - negative feedback