Skip to content

Commit

Permalink
多端登录自动踢下线
Browse files Browse the repository at this point in the history
  • Loading branch information
lenve committed May 7, 2020
1 parent c53f09b commit 3b0a057
Show file tree
Hide file tree
Showing 23 changed files with 122 additions and 49 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
node_modules/
.DS_Store
/dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.idea
target/
*.iml
!.mvn/wrapper/maven-wrapper.jar
vhr.wiki
人事管理系统需求规格说明书.doc
人事管理系统需求规格说明书.doc
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

public class Hr implements UserDetails {
private Integer id;
Expand All @@ -32,6 +32,19 @@ public class Hr implements UserDetails {
private String remark;
private List<Role> roles;

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Hr hr = (Hr) o;
return Objects.equals(username, hr.username);
}

@Override
public int hashCode() {
return Objects.hash(username);
}

public List<Role> getRoles() {
return roles;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package org.javaboy.vhr.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.javaboy.vhr.model.Hr;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.http.HttpServletRequest;
Expand All @@ -23,6 +26,8 @@
* @Gitee https://gitee.com/lenve
*/
public class LoginFilter extends UsernamePasswordAuthenticationFilter {
@Autowired
SessionRegistry sessionRegistry;
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (!request.getMethod().equals("POST")) {
Expand Down Expand Up @@ -51,6 +56,9 @@ public Authentication attemptAuthentication(HttpServletRequest request, HttpServ
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
username, password);
setDetails(request, authRequest);
Hr principal = new Hr();
principal.setUsername(username);
sessionRegistry.registerNewSession(request.getSession(true).getId(), principal);
return this.getAuthenticationManager().authenticate(authRequest);
} else {
checkCode(response, request.getParameter("code"), verify_code);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy;
import org.springframework.security.web.session.ConcurrentSessionFilter;

import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

/**
Expand Down Expand Up @@ -89,9 +93,17 @@ LoginFilter loginFilter() throws Exception {
);
loginFilter.setAuthenticationManager(authenticationManagerBean());
loginFilter.setFilterProcessesUrl("/doLogin");
ConcurrentSessionControlAuthenticationStrategy sessionStrategy = new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry());
sessionStrategy.setMaximumSessions(1);
loginFilter.setSessionAuthenticationStrategy(sessionStrategy);
return loginFilter;
}

@Bean
SessionRegistryImpl sessionRegistry() {
return new SessionRegistryImpl();
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
Expand Down Expand Up @@ -130,6 +142,15 @@ public <O extends FilterSecurityInterceptor> O postProcess(O object) {
out.close();
}
);
http.addFilterAt(new ConcurrentSessionFilter(sessionRegistry(), event -> {
HttpServletResponse resp = event.getResponse();
resp.setContentType("application/json;charset=utf-8");
resp.setStatus(401);
PrintWriter out = resp.getWriter();
out.write(new ObjectMapper().writeValueAsString(RespBean.error("您已在另一台设备登录,本次登录已下线!")));
out.flush();
out.close();
}), ConcurrentSessionFilter.class);
http.addFilterAt(loginFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
2 changes: 1 addition & 1 deletion vhr/vhrserver/vhr-web/src/main/resources/static/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.ico><title>vuehr</title><link href=/css/chunk-0c17a57a.9fe19f94.css rel=prefetch><link href=/css/chunk-64435448.3755e146.css rel=prefetch><link href=/js/chunk-0c17a57a.3d783b80.js rel=prefetch><link href=/js/chunk-18458ebc.2dd3c93a.js rel=prefetch><link href=/js/chunk-2d0d03c8.3a093d55.js rel=prefetch><link href=/js/chunk-2d237c54.0b312051.js rel=prefetch><link href=/js/chunk-33b8cd94.a94483af.js rel=prefetch><link href=/js/chunk-4e552d82.57eb10c5.js rel=prefetch><link href=/js/chunk-64435448.c8d2ed8f.js rel=prefetch><link href=/js/chunk-df7e035a.c9947309.js rel=prefetch><link href=/css/app.4e8a7623.css rel=preload as=style><link href=/css/chunk-vendors.b2d517d7.css rel=preload as=style><link href=/js/app.822dbe74.js rel=preload as=script><link href=/js/chunk-vendors.1b439e36.js rel=preload as=script><link href=/css/chunk-vendors.b2d517d7.css rel=stylesheet><link href=/css/app.4e8a7623.css rel=stylesheet></head><body style="margin:0px;padding: 0px;"><noscript><strong>We're sorry but vuehr doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.1b439e36.js></script><script src=/js/app.822dbe74.js></script></body></html>
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.ico><title>vuehr</title><link href=/css/chunk-0c17a57a.42916da5.css rel=prefetch><link href=/css/chunk-64435448.3755e146.css rel=prefetch><link href=/js/chunk-0c17a57a.3d783b80.js rel=prefetch><link href=/js/chunk-18458ebc.2dd3c93a.js rel=prefetch><link href=/js/chunk-2d0d03c8.3a093d55.js rel=prefetch><link href=/js/chunk-2d237c54.0b312051.js rel=prefetch><link href=/js/chunk-33b8cd94.a94483af.js rel=prefetch><link href=/js/chunk-4e552d82.57eb10c5.js rel=prefetch><link href=/js/chunk-64435448.c8d2ed8f.js rel=prefetch><link href=/js/chunk-df7e035a.c9947309.js rel=prefetch><link href=/css/app.4e8a7623.css rel=preload as=style><link href=/css/chunk-vendors.c805ba07.css rel=preload as=style><link href=/js/app.36643c7a.js rel=preload as=script><link href=/js/chunk-vendors.0a8f9d11.js rel=preload as=script><link href=/css/chunk-vendors.c805ba07.css rel=stylesheet><link href=/css/app.4e8a7623.css rel=stylesheet></head><body style="margin:0px;padding: 0px;"><noscript><strong>We're sorry but vuehr doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.0a8f9d11.js></script><script src=/js/app.36643c7a.js></script></body></html>
Binary file modified vhr/vhrserver/vhr-web/src/main/resources/static/index.html.gz
Binary file not shown.

Large diffs are not rendered by default.

Binary file not shown.

Large diffs are not rendered by default.

This file was deleted.

Binary file not shown.

This file was deleted.

Large diffs are not rendered by default.

Binary file not shown.

Large diffs are not rendered by default.

This file was deleted.

Binary file not shown.

This file was deleted.

3 changes: 2 additions & 1 deletion vuehr/src/utils/api.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import axios from 'axios'
import {Message} from 'element-ui';
import router from '../router'
import {mymessage} from '@/utils/mymessage';

axios.interceptors.response.use(success => {
if (success.status && success.status == 200 && success.data.status == 500) {
Expand All @@ -17,7 +18,7 @@ axios.interceptors.response.use(success => {
} else if (error.response.status == 403) {
Message.error({message: '权限不足,请联系管理员'})
} else if (error.response.status == 401) {
Message.error({message: '尚未登录,请登录'})
mymessage.error({message: error.response.data.msg ? error.response.data.msg : '尚未登录,请登录'})
router.replace('/');
} else {
if (error.response.data.msg) {
Expand Down
28 changes: 28 additions & 0 deletions vuehr/src/utils/mymessage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {
Message
} from 'element-ui';
const showMessage = Symbol('showMessage')
class JavaboyMessage {
[showMessage](type, options, single) {
if (single) {
if (document.getElementsByClassName('el-message').length === 0) {
Message[type](options)
}
} else {
Message[type](options)
}
}
info(options, single = true) {
this[showMessage]('info', options, single)
}
warning(options, single = true) {
this[showMessage]('warning', options, single)
}
error(options, single = true) {
this[showMessage]('error', options, single)
}
success(options, single = true) {
this[showMessage]('success', options, single)
}
}
export const mymessage = new JavaboyMessage();

0 comments on commit 3b0a057

Please sign in to comment.