统计模块功能编写及sessionId管理自定义

pull/1/head
陈沅 2 years ago
parent 44fdd9ba13
commit 92d18febea

@ -0,0 +1,151 @@
package com.sztzjy.forex.trading_trading.config.security;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.log.LogMessage;
import org.springframework.security.core.session.*;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* session
* SessionRegistryImplregisterNewSessionidid
* 便sessionId
*
* @author
* @date 2023/07/06 22:27:47
*/
@Component
public class CustomSessionRegistry implements SessionRegistry {
protected final Log logger = LogFactory.getLog(CustomSessionRegistry.class);
private final ConcurrentMap<Object, Set<String>> principals;
private final Map<String, SessionInformation> sessionIds;
public CustomSessionRegistry() {
this.principals = new ConcurrentHashMap();
this.sessionIds = new ConcurrentHashMap();
}
public CustomSessionRegistry(ConcurrentMap<Object, Set<String>> principals, Map<String, SessionInformation> sessionIds) {
this.principals = principals;
this.sessionIds = sessionIds;
}
public List<Object> getAllPrincipals() {
return new ArrayList(this.principals.keySet());
}
public List<SessionInformation> getAllSessions(Object principal, boolean includeExpiredSessions) {
Set<String> sessionsUsedByPrincipal = (Set)this.principals.get(principal);
if (sessionsUsedByPrincipal == null) {
return Collections.emptyList();
} else {
List<SessionInformation> list = new ArrayList(sessionsUsedByPrincipal.size());
Iterator var5 = sessionsUsedByPrincipal.iterator();
while(true) {
SessionInformation sessionInformation;
do {
do {
if (!var5.hasNext()) {
return list;
}
String sessionId = (String)var5.next();
sessionInformation = this.getSessionInformation(sessionId);
} while(sessionInformation == null);
} while(!includeExpiredSessions && sessionInformation.isExpired());
list.add(sessionInformation);
}
}
}
public SessionInformation getSessionInformation(String sessionId) {
Assert.hasText(sessionId, "SessionId required as per interface contract");
return (SessionInformation)this.sessionIds.get(sessionId);
}
public void onApplicationEvent(AbstractSessionEvent event) {
String oldSessionId;
if (event instanceof SessionDestroyedEvent) {
SessionDestroyedEvent sessionDestroyedEvent = (SessionDestroyedEvent)event;
oldSessionId = sessionDestroyedEvent.getId();
this.removeSessionInformation(oldSessionId);
} else if (event instanceof SessionIdChangedEvent) {
SessionIdChangedEvent sessionIdChangedEvent = (SessionIdChangedEvent)event;
oldSessionId = sessionIdChangedEvent.getOldSessionId();
if (this.sessionIds.containsKey(oldSessionId)) {
Object principal = ((SessionInformation)this.sessionIds.get(oldSessionId)).getPrincipal();
this.removeSessionInformation(oldSessionId);
this.registerNewSession(sessionIdChangedEvent.getNewSessionId(), principal);
}
}
}
public void refreshLastRequest(String sessionId) {
Assert.hasText(sessionId, "SessionId required as per interface contract");
SessionInformation info = this.getSessionInformation(sessionId);
if (info != null) {
info.refreshLastRequest();
}
}
public void registerNewSession(String sessionId, Object principal) {
Assert.hasText(sessionId, "SessionId required as per interface contract");
Assert.notNull(principal, "Principal required as per interface contract");
if(principal instanceof JwtUser){
sessionId = ((JwtUser) principal).getUsername();
}
if (this.getSessionInformation(sessionId) != null) {
this.removeSessionInformation(sessionId);
}
if (this.logger.isDebugEnabled()) {
this.logger.debug(LogMessage.format("Registering session %s, for principal %s", sessionId, principal));
}
this.sessionIds.put(sessionId, new SessionInformation(principal, sessionId, new Date()));
String finalSessionId = sessionId;
this.principals.compute(principal, (key, sessionsUsedByPrincipal) -> {
if (sessionsUsedByPrincipal == null) {
sessionsUsedByPrincipal = new CopyOnWriteArraySet();
}
((Set)sessionsUsedByPrincipal).add(finalSessionId);
this.logger.trace(LogMessage.format("Sessions used by '%s' : %s", principal, sessionsUsedByPrincipal));
return (Set)sessionsUsedByPrincipal;
});
}
public void removeSessionInformation(String sessionId) {
Assert.hasText(sessionId, "SessionId required as per interface contract");
SessionInformation info = this.getSessionInformation(sessionId);
if (info != null) {
if (this.logger.isTraceEnabled()) {
this.logger.debug("Removing session " + sessionId + " from set of registered sessions");
}
this.sessionIds.remove(sessionId);
this.principals.computeIfPresent(info.getPrincipal(), (key, sessionsUsedByPrincipal) -> {
this.logger.debug(LogMessage.format("Removing session %s from principal's set of registered sessions", sessionId));
sessionsUsedByPrincipal.remove(sessionId);
if (sessionsUsedByPrincipal.isEmpty()) {
this.logger.debug(LogMessage.format("Removing principal %s from registry", info.getPrincipal()));
sessionsUsedByPrincipal = null;
}
this.logger.trace(LogMessage.format("Sessions used by '%s' : %s", info.getPrincipal(), sessionsUsedByPrincipal));
return sessionsUsedByPrincipal;
});
}
}
}

@ -7,6 +7,7 @@ import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
/**
* jwt
@ -53,4 +54,18 @@ public class JwtUser implements UserDetails {
public boolean isEnabled() {
return false;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof JwtUser)) return false;
JwtUser user = (JwtUser) o;
return username.equals(user.username);
}
@Override
public int hashCode() {
return Objects.hash(username);
}
}

@ -12,6 +12,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@ -54,6 +55,12 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();
Set<String> anonymousUrls = discoveryAnonymousUrls(handlerMethods);
http
.sessionManagement(sessionManagement ->
sessionManagement
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.maximumSessions(1)
.sessionRegistry(sessionRegistry())
)
.addFilterBefore(new AuthenticationFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class)
.cors().and()
.headers().addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Headers", "Authorization"))
@ -64,12 +71,13 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
.authenticationEntryPoint(customAuthenticationEntryPoint)
.accessDeniedHandler(customAccessDeniedHandler)
// 防止iframe 造成跨域
.and().headers().frameOptions().disable()
.and().headers().frameOptions().disable().and()
// 不创建会话
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
// .and()
// .sessionManagement()
// .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
// .sessionRegistry(sessionRegistry())
// .and()
// 所有请求都需要认证
.authorizeRequests()
.antMatchers("/swagger-resources/**").permitAll()
@ -82,6 +90,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
.anyRequest().authenticated();
}
/**
*
*
@ -114,4 +123,10 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
return patterns;
}
@Bean
public SessionRegistry sessionRegistry() {
return new CustomSessionRegistry();
}
}

@ -1,6 +1,7 @@
package com.sztzjy.forex.trading_trading.controller;
import com.sztzjy.forex.trading_trading.annotation.AnonymousAccess;
import com.sztzjy.forex.trading_trading.config.security.JwtUser;
import com.sztzjy.forex.trading_trading.dto.PageVO;
import com.sztzjy.forex.trading_trading.entity.Log;
import com.sztzjy.forex.trading_trading.service.LogService;
@ -11,11 +12,17 @@ import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@Api(tags = "系统:操作日志")
@RestController
@RequestMapping("api/syslog")
@ -38,4 +45,6 @@ public class LogController {
pageVO.setPageInfo(page, page.getContent());
return new ResultEntity<>(HttpStatus.OK, pageVO);
}
}

@ -0,0 +1,43 @@
package com.sztzjy.forex.trading_trading.controller;
import com.sztzjy.forex.trading_trading.annotation.Permission;
import com.sztzjy.forex.trading_trading.annotation.aspect.PermissionType;
import com.sztzjy.forex.trading_trading.config.security.JwtUser;
import com.sztzjy.forex.trading_trading.config.security.TokenProvider;
import com.sztzjy.forex.trading_trading.mappers.MemberMapper;
import com.sztzjy.forex.trading_trading.service.MemberService;
import com.sztzjy.forex.trading_trading.util.ResultEntity;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
@Api(tags = "统计管理")
@RestController
@RequiredArgsConstructor
@RequestMapping("api/statistical")
public class StatisticalController {
private final HttpServletRequest request;
private final MemberService memberService;
@Permission(codes = PermissionType.DATA_STATISTICS)
@ApiOperation("教师端----班级成绩走势统计")
@GetMapping("classScoreTrend")
public ResultEntity<List<Map<String,Object>>> classScoreTrend() {
JwtUser currentUser = TokenProvider.getJWTUser(request);
return new ResultEntity(HttpStatus.OK,memberService.classScoreTrend(currentUser.getSchoolId()));
}
}

@ -30,7 +30,6 @@ public class TrainingLessonPlanController {
private final TrainingLessonPlanService trainingLessonPlanService;
private final HttpServletRequest request;
private final IFileUtil fileUtil;
@Permission(codes = PermissionType.TRAINING_PLAN_MANAGEMENT_ADD)
@ -64,7 +63,7 @@ public class TrainingLessonPlanController {
}
@Permission(codes = PermissionType.TRAINING_PLAN_MANAGEMENT_SEARCH)
@ApiOperation("根据教案名字查询教案")
@ApiOperation("根据教案名字查询教案(分页展示)")
@GetMapping("findByName")
public ResultEntity<PageInfo<TrainingLessonPlan>> findByName(@ApiParam("教案名称") @RequestParam String name,
@ApiParam("分页索引:{0}为第一页") @RequestParam(required = false) Integer index,

@ -14,20 +14,21 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Api(tags = "用户管理模块")
@RestController
@ -35,8 +36,10 @@ import javax.annotation.Resource;
@RequiredArgsConstructor
public class UserController {
@Autowired
private RoleAuthorityService roleAuthorityService;
private final RoleAuthorityService roleAuthorityService;
private final SessionRegistry sessionRegistry;
@AnonymousAccess
@OperateLog(description = "用户登录")
@ -75,6 +78,43 @@ public class UserController {
return new ResultEntity<LoginResult>(LoginResult.create(jwtUser, token));
}
@ApiOperation(value = "注销登录", httpMethod = "POST")
@PostMapping("/logout")
public ResultEntity logout(HttpServletRequest request) {
// 获取当前认证信息
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) {
// 执行注销操作
new SecurityContextLogoutHandler().logout(request, null, authentication);
sessionRegistry.removeSessionInformation(request.getSession().getId());
}
return new ResultEntity(HttpStatus.OK);
}
// @Permission()
@AnonymousAccess
@ApiOperation("获取当前在线用户")
@GetMapping("online-users")
public Set<String> getOnlineUsers() {
List<Object> principals = sessionRegistry.getAllPrincipals();
Set<String> usernames = new HashSet<>();
for (Object principal : principals) {
if (principal instanceof JwtUser) {
JwtUser user = (JwtUser) principal;
List<SessionInformation> sessions = sessionRegistry.getAllSessions(user, false);
if (!sessions.isEmpty()) {
usernames.add(user.getUsername());
}
}
}
return usernames;
}
}

@ -3,10 +3,13 @@ package com.sztzjy.forex.trading_trading.mappers;
import com.sztzjy.forex.trading_trading.dto.MemberVO;
import com.sztzjy.forex.trading_trading.entity.Member;
import com.sztzjy.forex.trading_trading.entity.MemberExample;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface MemberMapper {
@ -62,7 +65,6 @@ public interface MemberMapper {
List<Member> selectByExample(MemberExample example);
List<MemberVO> pagedListMembers(MemberExample example);
/**
@ -104,4 +106,28 @@ public interface MemberMapper {
* @mbg.generated Fri Jun 30 14:15:42 CST 2023
*/
int updateByPrimaryKey(Member record);
@Select("SELECT" +
" training_name," +
" class_grade," +
" (" +
" SUM((" +
" SELECT" +
" actual_score " +
" FROM" +
" sys_grade_weight " +
" WHERE" +
" max_profit > sys_member.yield " +
" AND min_profit <= sys_member.yield " +
" AND weight_id = ( SELECT weight_id FROM sys_grade_weight WHERE school_id = " +
"sys_member.school_id ORDER BY create_time DESC LIMIT 1 )))+ 50 " +//该位置+50是报告的分数
" )/ count( 1 ) AS avgScore " +
"FROM" +
" sys_member " +
"WHERE" +
" school_id = #{schoolId} " +
"GROUP BY" +
" training_name," +
" class_grade")
List<Map<String, Object>> classScoreTrend(@Param("schoolId") Integer schoolId);
}

@ -20,6 +20,7 @@ import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@Service
public class MemberService {
@ -132,4 +133,8 @@ public class MemberService {
fileUtil.download(response, fileName);
fileUtil.remove(file);
}
public List<Map<String,Object>> classScoreTrend(Integer schoolId){
return memberMapper.classScoreTrend(schoolId);
}
}

Loading…
Cancel
Save