Commit 4c43fb75 authored by suntao's avatar suntao

login and out

parent 1cc273a6
package cn.quantgroup.cashloanflowboss.api.login.controller; package cn.quantgroup.cashloanflowboss.api.login.controller;
import cn.quantgroup.cashloanflowboss.api.login.model.LoginFormModel; import cn.quantgroup.cashloanflowboss.api.login.model.LoginFormModel;
import cn.quantgroup.cashloanflowboss.api.login.service.LogService; import cn.quantgroup.cashloanflowboss.api.login.service.LoginService;
import cn.quantgroup.cashloanflowboss.component.security.Authority; import cn.quantgroup.cashloanflowboss.component.security.Authority;
import cn.quantgroup.cashloanflowboss.component.security.annotiation.Security; import cn.quantgroup.cashloanflowboss.component.security.annotiation.Security;
import cn.quantgroup.cashloanflowboss.core.base.Result; import cn.quantgroup.cashloanflowboss.core.base.Result;
...@@ -21,7 +21,7 @@ import javax.validation.Valid; ...@@ -21,7 +21,7 @@ import javax.validation.Valid;
public class LogController { public class LogController {
@Autowired @Autowired
private LogService logService; private LoginService loginService;
/** /**
* 登入 * 登入
...@@ -31,7 +31,7 @@ public class LogController { ...@@ -31,7 +31,7 @@ public class LogController {
*/ */
@PostMapping("/login") @PostMapping("/login")
public Result<String> login(@RequestBody @Valid LoginFormModel loginFormModel) { public Result<String> login(@RequestBody @Valid LoginFormModel loginFormModel) {
return new Result<>(ApplicationStatus.SUCCESS, this.logService.login(loginFormModel.getUsername(), loginFormModel.getPassword())); return new Result<>(ApplicationStatus.SUCCESS, this.loginService.login(loginFormModel.getUsername(), loginFormModel.getPassword()));
} }
/** /**
...@@ -42,7 +42,7 @@ public class LogController { ...@@ -42,7 +42,7 @@ public class LogController {
@DeleteMapping("/logout") @DeleteMapping("/logout")
@Security(authorityId = "Log.logout", authorities = Authority.READ) @Security(authorityId = "Log.logout", authorities = Authority.READ)
public Result<Boolean> logout() { public Result<Boolean> logout() {
return new Result<>(ApplicationStatus.SUCCESS, this.logService.logout()); return new Result<>(ApplicationStatus.SUCCESS, this.loginService.logout());
} }
} }
package cn.quantgroup.cashloanflowboss.api.login.service;
import java.util.Map;
/**
* function:
* date: 2019/10/28
*
* @author: suntao
*/
public interface LoginService {
String login(String username, String password);
boolean logout();
Map<String, Object> getConcurrentHashMapLoginInfo();
}
...@@ -16,13 +16,16 @@ import org.springframework.stereotype.Service; ...@@ -16,13 +16,16 @@ import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* Created by WeiWei on 2019/7/22. * Created by WeiWei on 2019/7/22.
*/ */
@Slf4j @Slf4j
@Service @Service
public class LogService { public class LoginServiceImpl implements LoginService {
@Autowired @Autowired
private UserServiceImpl userService; private UserServiceImpl userService;
...@@ -30,6 +33,11 @@ public class LogService { ...@@ -30,6 +33,11 @@ public class LogService {
@Autowired @Autowired
private HttpServletRequest request; private HttpServletRequest request;
/**
* 用户为key,登陆信息(最后登陆时间)
*/
private ConcurrentHashMap<String, Object> loginInfo = new ConcurrentHashMap<>(8);
/** /**
* 登入 * 登入
* *
...@@ -37,6 +45,7 @@ public class LogService { ...@@ -37,6 +45,7 @@ public class LogService {
* @param password 密码(明文) * @param password 密码(明文)
* @return * @return
*/ */
@Override
public String login(String username, String password) { public String login(String username, String password) {
User user = this.userService.getUser(username); User user = this.userService.getUser(username);
...@@ -66,6 +75,9 @@ public class LogService { ...@@ -66,6 +75,9 @@ public class LogService {
principal.setRoles(user.getRoles()); principal.setRoles(user.getRoles());
session.setAttribute(ApplicationDictionary.PRINCIPAL, JSONTools.serialize(principal)); session.setAttribute(ApplicationDictionary.PRINCIPAL, JSONTools.serialize(principal));
// session登陆时间,毫秒值
// 用户登陆时间,毫秒值
loginInfo.put(userInfo.getUserId() + "", session.getLastAccessedTime());
return session.getId(); return session.getId();
...@@ -76,6 +88,7 @@ public class LogService { ...@@ -76,6 +88,7 @@ public class LogService {
* *
* @return * @return
*/ */
@Override
public boolean logout() { public boolean logout() {
this.request.getSession().removeAttribute(ApplicationDictionary.PRINCIPAL); this.request.getSession().removeAttribute(ApplicationDictionary.PRINCIPAL);
...@@ -84,4 +97,9 @@ public class LogService { ...@@ -84,4 +97,9 @@ public class LogService {
} }
@Override
public Map<String, Object> getConcurrentHashMapLoginInfo() {
return loginInfo;
}
} }
...@@ -15,9 +15,11 @@ import org.springframework.web.context.request.ServletRequestAttributes; ...@@ -15,9 +15,11 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Validation; import javax.validation.Validation;
import javax.validation.Validator; import javax.validation.Validator;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* Created by WeiWei on 2017/5/23. * Created by WeiWei on 2017/5/23.
...@@ -29,6 +31,11 @@ public class Application implements ApplicationContextAware, ServletContextAware ...@@ -29,6 +31,11 @@ public class Application implements ApplicationContextAware, ServletContextAware
private static ServletContext servletContext; private static ServletContext servletContext;
/**
* 用户为key,登陆信息(最后登陆时间)
*/
private ConcurrentHashMap<String, Object> loginInfo;
public static ApplicationContext getApplicationContext() { public static ApplicationContext getApplicationContext() {
return applicationContext; return applicationContext;
...@@ -164,9 +171,19 @@ public class Application implements ApplicationContextAware, ServletContextAware ...@@ -164,9 +171,19 @@ public class Application implements ApplicationContextAware, ServletContextAware
*/ */
public static Principal getPrincipal() { public static Principal getPrincipal() {
return Objects.nonNull(getSession()) ? JSONTools.deserialize(String.valueOf(getSession().getAttribute(ApplicationDictionary.PRINCIPAL)), Principal.class) : null;
}
/**
* 获取用户主要信息
*
* @return
*/
public static HttpSession getSession() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
return Objects.nonNull(request) && Objects.nonNull(request.getSession()) ? JSONTools.deserialize(String.valueOf(request.getSession().getAttribute(ApplicationDictionary.PRINCIPAL)), Principal.class) : null; return Objects.nonNull(request) && Objects.nonNull(request.getSession()) ? request.getSession() : null;
} }
......
package cn.quantgroup.cashloanflowboss.core.asserts; package cn.quantgroup.cashloanflowboss.core.asserts;
import cn.quantgroup.cashloanflowboss.api.login.model.Principal;
import cn.quantgroup.cashloanflowboss.core.Application;
import cn.quantgroup.cashloanflowboss.core.dictionary.ApplicationDictionary;
import cn.quantgroup.cashloanflowboss.core.dictionary.ApplicationStatus;
import cn.quantgroup.cashloanflowboss.core.dictionary.Status; import cn.quantgroup.cashloanflowboss.core.dictionary.Status;
import cn.quantgroup.cashloanflowboss.core.exception.ApplicationException; import cn.quantgroup.cashloanflowboss.core.exception.ApplicationException;
import org.apache.commons.lang3.ObjectUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Collection; import java.util.Collection;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
/** /**
...@@ -313,4 +321,38 @@ public class Assert { ...@@ -313,4 +321,38 @@ public class Assert {
} }
} }
/**
* @param concurrentHashMapLoginInfo 账号最后登陆时间
* @param authenticationLoginCrowdOut
*/
public static void isLastLogin(Map<String, Object> concurrentHashMapLoginInfo, Status authenticationLoginCrowdOut) {
HttpSession session = Application.getSession();
if (Objects.isNull(session)) {
System.out.println("session 为空");
return;
}
Principal principal = Application.getPrincipal();
if (Objects.isNull(principal)) {
System.out.println("principal 为空");
return;
}
Object userLastLoginTimeObject = concurrentHashMapLoginInfo.get(principal.getUserInfo().getUserId()+"");
if (Objects.isNull(userLastLoginTimeObject)) {
// 没有登陆时间 不处理
System.out.println("userLastLoginTimeObject 为空");
return;
}
// 获取session最后登陆时间
Long lastAccessedTime = session.getLastAccessedTime();
if (Objects.isNull(lastAccessedTime)) {
System.out.println("lastAccessedTime 为空");
return;
}
if (lastAccessedTime < Long.valueOf(userLastLoginTimeObject.toString())) {
throw new ApplicationException(authenticationLoginCrowdOut);
}
}
} }
package cn.quantgroup.cashloanflowboss.core.configuration; package cn.quantgroup.cashloanflowboss.core.configuration;
import cn.quantgroup.cashloanflowboss.api.login.model.Principal; import cn.quantgroup.cashloanflowboss.api.login.model.Principal;
import cn.quantgroup.cashloanflowboss.api.login.service.LoginService;
import cn.quantgroup.cashloanflowboss.api.login.service.LoginServiceImpl;
import cn.quantgroup.cashloanflowboss.api.role.entity.Role; import cn.quantgroup.cashloanflowboss.api.role.entity.Role;
import cn.quantgroup.cashloanflowboss.component.security.Authority; import cn.quantgroup.cashloanflowboss.component.security.Authority;
import cn.quantgroup.cashloanflowboss.component.security.SecurityHandler; import cn.quantgroup.cashloanflowboss.component.security.SecurityHandler;
import cn.quantgroup.cashloanflowboss.core.Application; import cn.quantgroup.cashloanflowboss.core.Application;
import cn.quantgroup.cashloanflowboss.core.asserts.Assert; import cn.quantgroup.cashloanflowboss.core.asserts.Assert;
import cn.quantgroup.cashloanflowboss.core.dictionary.ApplicationStatus; import cn.quantgroup.cashloanflowboss.core.dictionary.ApplicationStatus;
import cn.quantgroup.cashloanflowboss.utils.JSONTools;
import org.aopalliance.intercept.MethodInvocation; import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
/** /**
* Created by WeiWei on 2019/7/26. * Created by WeiWei on 2019/7/26.
...@@ -23,6 +24,9 @@ import java.util.stream.Stream; ...@@ -23,6 +24,9 @@ import java.util.stream.Stream;
@Configuration @Configuration
public class ApplicationSecurityHandler implements SecurityHandler { public class ApplicationSecurityHandler implements SecurityHandler {
@Autowired
private LoginService loginService;
@Override @Override
public boolean doAuthentication(MethodInvocation invocation, String authorityId, Authority[] authority) throws Throwable { public boolean doAuthentication(MethodInvocation invocation, String authorityId, Authority[] authority) throws Throwable {
...@@ -31,8 +35,11 @@ public class ApplicationSecurityHandler implements SecurityHandler { ...@@ -31,8 +35,11 @@ public class ApplicationSecurityHandler implements SecurityHandler {
// 检查是否已登录 // 检查是否已登录
Assert.isNull(principal, ApplicationStatus.AUTHENTICATION_LOGIN); Assert.isNull(principal, ApplicationStatus.AUTHENTICATION_LOGIN);
// 如果是超级管理员跳过权限验证 // 是否 被挤下线
Assert.isLastLogin(loginService.getConcurrentHashMapLoginInfo(), ApplicationStatus.AUTHENTICATION_LOGIN_CROWD_OUT);
// 如果是超级管理员跳过权限验证
return principal.isSuperAdministrator() || principal.getRoles().stream().anyMatch(role -> { return principal.isSuperAdministrator() || principal.getRoles().stream().anyMatch(role -> {
List<Role> roleList = getRoleAndParent(role); List<Role> roleList = getRoleAndParent(role);
if (CollectionUtils.isEmpty(roleList)) { if (CollectionUtils.isEmpty(roleList)) {
......
...@@ -15,4 +15,7 @@ public final class ApplicationDictionary { ...@@ -15,4 +15,7 @@ public final class ApplicationDictionary {
// user Session key // user Session key
public static final String USER_KEY = "USER"; public static final String USER_KEY = "USER";
// user Session登陆时间 key
public static final String USER_SESSION_LOGIN_TIME = "USER_SESSION_LOGIN_TIME";
} }
...@@ -27,6 +27,8 @@ public enum ApplicationStatus implements Status<ApplicationStatus> { ...@@ -27,6 +27,8 @@ public enum ApplicationStatus implements Status<ApplicationStatus> {
AUTHENTICATION_LOGIN(500006, "请登录..."), AUTHENTICATION_LOGIN(500006, "请登录..."),
AUTHENTICATION_LOGIN_CROWD_OUT(500007, "账号已在其他地方登陆,请重新登录或者修改密码"),
INVALID_AUTHORITY(501001, "无效的授权"), INVALID_AUTHORITY(501001, "无效的授权"),
INVALID_USER(501002, "无效的用户"), INVALID_USER(501002, "无效的用户"),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment