提交 3b0a0571 编写于 作者: 江南一点雨

多端登录自动踢下线

上级 c53f09b7
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
\ No newline at end of file
人事管理系统需求规格说明书.doc
......@@ -5,10 +5,10 @@ import org.springframework.security.core.GrantedAuthority;
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;
......@@ -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;
}
......
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;
......@@ -23,6 +26,8 @@ import java.util.Map;
* @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")) {
......@@ -51,6 +56,9 @@ public class LoginFilter extends UsernamePasswordAuthenticationFilter {
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);
......
......@@ -13,11 +13,15 @@ import org.springframework.security.config.annotation.authentication.builders.Au
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;
/**
......@@ -89,9 +93,17 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
);
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()
......@@ -130,6 +142,15 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
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);
}
}
<!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>
\ No newline at end of file
<!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>
\ No newline at end of file
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) {
......@@ -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) {
......
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();
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册