在这里,我们将给大家分享关于代码登录springsecurity并且获取jsessionId的知识,让您更了解spring实现登录的本质,同时也会涉及到如何更有效地2537-springsecurit
在这里,我们将给大家分享关于代码登录spring security并且获取jsessionId的知识,让您更了解spring实现登录的本质,同时也会涉及到如何更有效地2537-springsecurity系列--关于session的管理2-session缓存和共享、8. Spring Boot中Spring Security Session管理、org.springframework.security.core.session.SessionInformation的实例源码、org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler的实例源码的内容。
本文目录一览:- 代码登录spring security并且获取jsessionId(spring实现登录)
- 2537-springsecurity系列--关于session的管理2-session缓存和共享
- 8. Spring Boot中Spring Security Session管理
- org.springframework.security.core.session.SessionInformation的实例源码
- org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler的实例源码
代码登录spring security并且获取jsessionId(spring实现登录)
@Autowired
@Qualifier("org.springframework.security.authenticationManager")
protected AuthenticationManager authenticationManager;
@RequestMapping(value = "/test")
public ModelAndView test(HttpServletRequest request,HttpServletResponse response){
//跳转首页
ModelAndView view = new ModelAndView("pages/index");
//使用用户名、密码生成可用AuthenticationToken(用户名:test,密码:123456)
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken("test", "123456");
//设置authenticationToken的details,主要获取请求信息
authenticationToken.setDetails(new WebAuthenticationDetails(request));
//使用authenticationManager接口中的anthenticate进行springsecurity认证
Authentication authenticatedUser = authenticationManager.authenticate(authenticationToken);
//将认证信息放入安全上下文中(此处为个人理解)
SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
//如果没有session,生成一个session并设置当前的securityContext
request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
//此sessionId为响应给浏览器的jsessionId(可在浏览器中查看cookie中的jsessionId与此值是否相等)
String sessionId = request.getSession().getId();
System.out.println(jsessionId);
return view;
}
2537-springsecurity系列--关于session的管理2-session缓存和共享
版本信息
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.14.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>1.5.14.RELEASE</version>
<!--实际里面spring-security-web的版本是4.2.7-->
</dependency>
需求
1.服务器重启后,用户不需要重新登录,进行session缓存
2.用户登录后,半小时内无操作,则将其session置为无效
3.多台服务器部署成应用集群,进行session共享
4.想自定义前端cookie的名称,不用用自定义的JSESSION名称
处理需求
需求1
SpringSession和SpringSecurity可自动配合,SpringSecurity会向SpringSession获取session信息和授权信息,并进行缓存,
在应用重启后,SpringSecurity获取到的是Redis中缓存的session信息,即可完成重启后不重复登录
需求2
配置server.session.timeout参数,单位是秒,最小值是一分钟即60秒,假设server.session.timeout=60,用户在登录后,会在redis存一条session信息
如果60秒内没有任何操作,该条session将失效。如果用户一直有操作和请求,SpringSession会刷新有效期,每次请求后都将重新计算60秒。
需求3
应用在配置时,公用一台Redis服务器即可,所有应用的SpringSecurity都会通过SpringSession来存取session,而SpringSession都指向同一台Redis服务器,即可达到session共享的效果
需求4
自定义一个CookieHttpSessionStrategy即可
@Bean
public CookieHttpSessionStrategy cookieHttpSessionStrategy() {
CookieHttpSessionStrategy strategy = new CookieHttpSessionStrategy();
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
cookieSerializer.setCookieName("gs");
cookieSerializer.setCookiePath("/");
cookieSerializer.setCookieMaxAge(60 * 60 * 24 * 30);
strategy.setCookieSerializer(cookieSerializer);
return strategy;
}
使用spring-session组件来管理web应用的session
依赖文件
springboot的版本
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.14.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
redis依赖和springsession的依赖
<!--redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<!--spring2.0以后默认的客户端是lettuce 需要手动指定成redis-->
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</exclusion>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!--redis依赖-->
<!--springsession的依赖-->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
<version>1.3.1.RELEASE</version>
</dependency>
<!--springsession的依赖-->
配置application.properties的配置文件
# spring session采用的数据源类型
spring.session.store-type=redis
#配置session在redis里的命名空间
#spring.session.redis.namespace=security_session
#配置session的保存触发方式
#spring.session.redis.flush-mode=on_save
# 应用的session过期时间
server.session.timeout=1800
redis配置参数
#The Redis settings
# Redis数据库索引(默认为0)
spring.redis.database=9
# Redis服务器地址
spring.redis.host=localhost
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=0
Redis初始化类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import redis.clients.jedis.JedisPoolConfig;
@Configuration
@EnableAutoConfiguration
public class RedisConfig {
private static Logger logger = LoggerFactory.getLogger(RedisConfig.class);
@Bean
@ConfigurationProperties(prefix = "spring.redis")
public JedisPoolConfig getRedisConfig() {
JedisPoolConfig config = new JedisPoolConfig();
return config;
}
@Bean
@ConfigurationProperties(prefix = "spring.redis")
public JedisConnectionFactory getConnectionFactory() {
JedisConnectionFactory factory = new JedisConnectionFactory();
JedisPoolConfig config = getRedisConfig();
factory.setPoolConfig(config);
logger.info("JedisConnectionFactory bean init success.");
return factory;
}
@Bean
public RedisTemplate<?, ?> getRedisTemplate() {
RedisTemplate<?, ?> template = new StringRedisTemplate(getConnectionFactory());
return template;
}
}
踩得坑
- springboot 2.0以上的版本和 1.3版本的SpringSession在兼容上有些问题
- 1.3版本的SpringSession可正常使用Redis进行session缓存,1.3版本的SpringSession在使用MongoDB时,会出现数据格式不兼容(存进去的数据和取出的数据不同,导致报错)
参考和官方文档:
https://docs.spring.io/spring-session/docs/current/reference/html5/guides/java-security.html 官方文档 使用spring-session来给sec提供session缓存支持
https://docs.spring.io/spring-session-data-mongodb/docs/2.0.2.RELEASE/reference/htmlsingle/boot-mongo.html Spring Session - Mongo Repositories
https://docs.spring.io/spring-session-data-mongodb/docs/2.0.2.RELEASE/reference/htmlsingle/ 使用mongodb管理session的文档
https://docs.spring.io/spring-session/docs/1.3.3.RELEASE/reference/html5/ spring-session1.3.3的文档 里面详细说明和demo(1.3.3操作redis的客户端换成了 Lettuce)
完整项目工程参考
https://github.com/starmoon1994/springsecurity-collection
8. Spring Boot中Spring Security Session管理
用户登录成功后,信息保存在服务器Session中,这节学习下如何管理这些Session。这节将在Spring Security短信验证码登录的基础上继续扩展。
Session超时设置
Session超时时间也就是用户登录的有效时间。要设置Session超时时间很简单,只需要在配置文件中添加:
server:
servlet:
session:
timeout: 3600
单位为秒,通过上面的配置,Session的有效期为一个小时。
值得注意的是,Session的最小有效期为60秒,也就是说即使你设置为小于60秒的值,其有效期还是为60秒。查看
TomcatServletWebServerFactory 的源码即可发现原因:
org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory
Session失效后,刷新页面后将跳转到认证页面,我们可以再添加一些配置,自定义Session失效后的一些行为。
在Spring Security中配置Session管理器,并配置Session失效后要跳转的URL:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加验证码校验过滤器
.addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加短信验证码校验过滤器
.formLogin() // 表单登录
.loginPage("/authentication/require") // 登录跳转 URL
.loginProcessingUrl("/login") // 处理表单登录 URL
.successHandler(authenticationSucessHandler)//处理登录成功
.failureHandler(authenticationFailureHandler)//处理登录失败
.and()
.rememberMe()
.tokenRepository(persistentTokenRepository()) // 配置 token 持久化仓库
.tokenValiditySeconds(3600) // remember 过期时间,单为秒
.userDetailsService(userDetailService) // 处理自动登录逻辑
.and()
.authorizeRequests() // 授权配置
.antMatchers("/authentication/require", "/login.html", "/code/image","/code/sms","/session/invalid").permitAll() // 登录跳转 URL 无需认证
.anyRequest() // 所有请求
.authenticated() // 都需要认证
.and()
.sessionManagement() // 添加 Session管理器
.invalidSessionUrl("/session/invalid") // Session失效后跳转到这个链接
.and().csrf().disable()
.apply(smsAuthenticationConfig);// 将短信验证码认证配置加到 Spring Security 中
}
上面配置了Session失效后跳转到/session/invalid
,并且将这个URL添加到了免认证路径中。
在Controller里添加一个方法,映射该请求:
@GetMapping("/session/invalid")
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public String sessionInvalid(){
return "session已失效,请重新认证";
}
我们将Session的超时时间设置为最小值60秒,重启项目,认证后等待60秒并刷新页面:
可看到请求跳转到了我们自定义的/session/invalid
URL上。
Session并发控制
Session并发控制可以控制一个账号同一时刻最多能登录多少个。我们在Spring Security配置中继续添加Session相关配置:
@Autowired
private MySessionExpiredStrategy sessionExpiredStrategy;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加验证码校验过滤器
.addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加短信验证码校验过滤器
.formLogin() // 表单登录
.loginPage("/authentication/require") // 登录跳转 URL
.loginProcessingUrl("/login") // 处理表单登录 URL
.successHandler(authenticationSucessHandler)//处理登录成功
.failureHandler(authenticationFailureHandler)//处理登录失败
.and()
.rememberMe()
.tokenRepository(persistentTokenRepository()) // 配置 token 持久化仓库
.tokenValiditySeconds(3600) // remember 过期时间,单为秒
.userDetailsService(userDetailService) // 处理自动登录逻辑
.and()
.authorizeRequests() // 授权配置
.antMatchers("/authentication/require", "/login.html", "/code/image","/code/sms","/session/invalid").permitAll() // 登录跳转 URL 无需认证
.anyRequest() // 所有请求
.authenticated() // 都需要认证
.and()
.sessionManagement() // 添加 Session管理器
.invalidSessionUrl("/session/invalid") // Session失效后跳转到这个链接
.maximumSessions(1)
.expiredSessionStrategy(sessionExpiredStrategy)
.and()
.and().csrf().disable()
.apply(smsAuthenticationConfig);// 将短信验证码认证配置加到 Spring Security 中
}
maximumSessions
配置了最大Session并发数量为1个,如果mrbird这个账户登录后,在另一个客户端也使用mrbird账户登录,那么第一个使用mrbird登录的账户将会失效,类似于一个先入先出队列。expiredSessionStrategy
配置了Session在并发下失效后的处理策略,这里为我们自定义的策略MySessionExpiredStrategy
。
MySessionExpiredStrategy
实现SessionInformationExpiredStrategy
:
@Component
public class MySessionExpiredStrategy implements SessionInformationExpiredStrategy {
@Override
public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
HttpServletResponse response = event.getResponse();
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("您的账号已经在别的地方登录,当前登录已失效。如果密码遭到泄露,请立即修改密码!");
}
}
为了演示这个效果,我们先将Session超时时间设置久一点,比如3600秒,然后重启项目,在Chrome里使用admin账户登录。
登录成功后,在firefox上也是用admin账户登录,登录成功后回到chrome,刷新页面,效果如下所示:
除了后者将前者踢出的策略,我们也可以控制当Session达到最大有效数的时候,不再允许相同的账户登录。
要实现这个功能只需要在上面的配置中添加:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加验证码校验过滤器
.addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加短信验证码校验过滤器
.formLogin() // 表单登录
.loginPage("/authentication/require") // 登录跳转 URL
.loginProcessingUrl("/login") // 处理表单登录 URL
.successHandler(authenticationSucessHandler)//处理登录成功
.failureHandler(authenticationFailureHandler)//处理登录失败
.and()
.rememberMe()
.tokenRepository(persistentTokenRepository()) // 配置 token 持久化仓库
.tokenValiditySeconds(3600) // remember 过期时间,单为秒
.userDetailsService(userDetailService) // 处理自动登录逻辑
.and()
.authorizeRequests() // 授权配置
.antMatchers("/authentication/require", "/login.html", "/code/image","/code/sms","/session/invalid").permitAll() // 登录跳转 URL 无需认证
.anyRequest() // 所有请求
.authenticated() // 都需要认证
.and()
.sessionManagement() // 添加 Session管理器
.invalidSessionUrl("/session/invalid") // Session失效后跳转到这个链接
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
.expiredSessionStrategy(sessionExpiredStrategy)
.and()
.and().csrf().disable()
.apply(smsAuthenticationConfig);// 将短信验证码认证配置加到 Spring Security 中
}
重启系统,在chrome上登录admin账户后,在firefox上尝试使用admin账户登录:
可以看到登录受限。
org.springframework.security.core.session.SessionInformation的实例源码
@Override protected void allowableSessionsExceeded(List<Sessioninformation> sessions,int allowableSessions,SessionRegistry registry) throws SessionAuthenticationException { Sessioninformation leastRecentlyUsed = null; for (Sessioninformation session : sessions) { if ((leastRecentlyUsed == null) || session.getLastRequest().before(leastRecentlyUsed.getLastRequest())) { leastRecentlyUsed = session; } } if(leastRecentlyUsed instanceof SessioninformationObject){ SessioninformationObject sessionObject=(SessioninformationObject)leastRecentlyUsed; sessionObject.setKickAway(true); } leastRecentlyUsed.expireNow(); }
@Test @WithMockUser("user123") public void testFindProfileActiveSessions() throws Exception { final UserEntity user = new UserEntity().setUsername("user123"); when(sessionRegistry.getAllPrincipals()).thenReturn(Collections.singletonList(user)); final Sessioninformation sessioninformation = new Sessioninformation("1","1",new Date()); when(sessionRegistry.getAllSessions(user,true)) .thenReturn(Collections.singletonList(sessioninformation)); MockHttpServletRequestBuilder request = get("/api/profile/sessions") .contentType(MediaType.APPLICATION_JSON); MockHttpServletResponse response = mockmvc.perform(request) .andDo(document("user-profile-sessions-list")) .andReturn() .getResponse(); assertthat(response.getStatus()).isEqualTo(200); List<Sessioninformation> expectedValue = Collections .singletonList(new Sessioninformation("user123",sessioninformation.getLastRequest())); assertthat(response.getContentAsByteArray()).isEqualTo(objectMapper.writeValueAsBytes(expectedValue)); verify(sessionRegistry).getAllPrincipals(); verify(sessionRegistry).getAllSessions(user,true); }
@Override @PreAuthorize("hasRole('ROLE_ADMIN')") public void kickUser(String ssoId){ final List<Object> allPrincipals = sessionRegistry.getAllPrincipals(); for (final Object principal : allPrincipals) { if (principal instanceof UserDetails && ((UserDetails) principal).getUsername().equals(ssoId)) { List<Sessioninformation> activeUserSessions = sessionRegistry.getAllSessions(principal,false); if (!activeUserSessions.isEmpty()) { for(Sessioninformation i : activeUserSessions){ i.expireNow(); } } } } }
public List<Sessioninformation> getAllSessions(Object principal,boolean includeExpiredSessions) { final Set<String> sessionsUsedByPrincipal = principals.get(principal); if (sessionsUsedByPrincipal == null) { return Collections.emptyList(); } List<Sessioninformation> list = new ArrayList<Sessioninformation>(sessionsUsedByPrincipal.size()); for (String sessionId : sessionsUsedByPrincipal) { Sessioninformation sessioninformation = getSessioninformation(sessionId); if (sessioninformation == null) { continue; } if (includeExpiredSessions || !sessioninformation.isExpired()) { list.add(sessioninformation); } } return list; }
@RequestMapping(value = "/expire.xhtml",method = RequestMethod.GET) public String expireSession(Model model,@RequestParam("session") String sessionid,RedirectAttributes redirectAttributes) { boolean expire = true; Object[] principals = cojSessionRegistryImpl.getAllPrincipals().toArray(); for (int i = 0; i < principals.length && expire; i++) { Object[] sessions = cojSessionRegistryImpl.getAllSessions(principals[i],true).toArray(); for (int j = 0; j < sessions.length && expire; j++) { Sessioninformation s = (Sessioninformation) sessions[j]; if (sessionid.equals(s.getSessionId())) { s.expireNow(); s.refreshLastRequest(); expire = false; cojSessionRegistryImpl.removeSessioninformation(sessionid); } } } redirectAttributes.addFlashAttribute("message",Notification.getSuccesfullDelete()); return "redirect:/admin/sessions.xhtml"; }
@modelattribute("activeUsers") public Map<Object,Date> listActiveUsers(Model model) { Map<Object,Date> lastActivityDates = new HashMap<Object,Date>(); for (Object principal : sessionRegistry.getAllPrincipals()) { for (Sessioninformation session : sessionRegistry.getAllSessions(principal,false)) { if (lastActivityDates.get(principal) == null) { lastActivityDates.put(principal,session.getLastRequest()); } else { Date prevLastRequest = lastActivityDates.get(principal); if (session.getLastRequest().after(prevLastRequest)) { lastActivityDates.put(principal,session.getLastRequest()); } } } } return lastActivityDates; }
@RequestMapping(value = "/logoutUsers",method = RequestMethod.GET) @ResponseBody public String logoutUsers(HttpServletRequest req,HttpServletResponse res) { String sessionId = req.getRequestedSessionId(); System.out.print("sessionId;:"+sessionId); JSONObject resJson = new JSONObject(); LOGGER.log(Level.INFO,"EXPIRE SESSION::::::"+sessionId); logout(req); if(sessionId!=null) { //List<Object> principals = sessionRegistry.getAllPrincipals(); sessionRegistry.removeSessioninformation(sessionId); if(sessionRegistry.getSessioninformation(sessionId) != null){ Sessioninformation session = sessionRegistry.getSessioninformation(sessionId); boolean isexpired = sessionRegistry.getSessioninformation(sessionId).isExpired(); resJson.put("isexpired",isexpired); if(!isexpired) { sessionRegistry.getSessioninformation(sessionId).expireNow(); } } resJson.put("Result",0); resJson.put("msg","Successfully logged out on LeafSchool"); } return resJson.toString(); }
@Override public List<Sessioninformation> getAllSessions(Object principal,boolean includeExpiredSessions) { Collection<S> sessions = this.sessionRepository.findByIndexNameAndindexValue( FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,name(principal)).values(); List<Sessioninformation> infos = new ArrayList<>(); for (S session : sessions) { if (includeExpiredSessions || !Boolean.TRUE.equals(session .getAttribute(SpringSessionBackedSessioninformation.EXPIRED_ATTR))) { infos.add(new SpringSessionBackedSessioninformation<>(session,this.sessionRepository)); } } return infos; }
@Test public void expireNow() { Session session = createSession(SESSION_ID,USER_NAME,Now); when(this.sessionRepository.findById(SESSION_ID)).thenReturn(session); Sessioninformation sessionInfo = this.sessionRegistry .getSessioninformation(SESSION_ID); assertthat(sessionInfo.isExpired()).isFalse(); sessionInfo.expireNow(); assertthat(sessionInfo.isExpired()).isTrue(); ArgumentCaptor<Session> captor = ArgumentCaptor.forClass(Session.class); verify(this.sessionRepository).save(captor.capture()); assertthat(captor.getValue().<Boolean>getAttribute( SpringSessionBackedSessioninformation.EXPIRED_ATTR)) .isEqualTo(Boolean.TRUE); }
@Override public List<Object> getAllPrincipals() { logger.debug("getAllPrincipals"); Map allSessions = sessionIds.getAllWithLoader(sessionIds.getKeys(),null); Set<Object> principals = new HashSet<Object>(); for (Object valObj : allSessions.values()) { Sessioninformation info = (Sessioninformation)valObj; principals.add(info.getPrincipal()); } List<Object> principalsList = new ArrayList<Object>(principals.size()); principalsList.addAll(principals); return principalsList; }
@Override public List<Sessioninformation> getAllSessions(Object principal,boolean includeExpiredSessions) { logger.debug("Called with includeExpiredSession "+includeExpiredSessions); Set<String> sessionsUsedByPrincipal = getSessionIds(principal); List<Sessioninformation> list = new ArrayList<Sessioninformation>(); Iterator<String> iter = sessionsUsedByPrincipal.iterator(); while (iter.hasNext()) { String sessionId = iter.next(); Sessioninformation sessioninformation = getSessioninformation(sessionId); if (includeExpiredSessions || !sessioninformation.isExpired()) { list.add(sessioninformation); } } logger.debug("List size "+list.size()); return list; }
@GetMapping("/sessions") public List<Sessioninformation> findProfileActiveSessions(Authentication authentication) { if (authentication == null || authentication.getPrincipal() == null) return Collections.emptyList(); List<Sessioninformation> sessions = new ArrayList<>(); for (Object principal : sessionRegistry.getAllPrincipals()) { UserEntity user = (UserEntity) principal; if (!user.getUsername().equals(authentication.getName())) continue; sessions.addAll(sessionRegistry.getAllSessions(user,true)); } return sessions.stream() .map(i -> new Sessioninformation(authentication.getName(),i.getSessionId(),i.getLastRequest())) .collect(Collectors.toList()); }
@RequestMapping(value = "list",method = RequestMethod.GET) public ModelMap list() { ModelMap map = new ModelMap(); List<Sessioninformation> sessions = new ArrayList<>(); for(Object principal : this.sessionRegistry.getAllPrincipals()) { sessions.addAll(this.sessionRegistry.getAllSessions(principal,true)); } map.put("timestamp",System.currentTimeMillis()); map.put("numberOfSessions",sessions.size()); map.put("sessions",sessions); return map; }
@DeleteMapping(value="/user/sessions/{sessionId}") public String removeSession(@PathVariable String sessionId,RedirectAttributes redirectAttrs) { Sessioninformation sessioninformation = sessionRegistry.getSessioninformation(sessionId); if(sessioninformation != null) { sessioninformation.expireNow(); } redirectAttrs.addFlashAttribute("message","Session was removed"); return "redirect:/user/sessions/"; }
@RequestMapping(value="/user/sessions/{sessionId}",method = RequestMethod.DELETE) public String removeSession(@PathVariable String sessionId,"Session was removed"); return "redirect:/user/sessions/"; }
@Override @PreAuthorize("isAnonymous() or isAuthenticated()") public boolean isUserOnline(String ssoId){ final List<Object> allPrincipals = sessionRegistry.getAllPrincipals(); for (final Object principal : allPrincipals) { if (principal instanceof UserDetails && ((UserDetails) principal).getUsername().equals(ssoId)) { List<Sessioninformation> activeUserSessions = sessionRegistry.getAllSessions(principal,false); if (!activeUserSessions.isEmpty()) { return true; } } } return false; }
public void refreshLastRequest(String sessionId) { Assert.hasText(sessionId,"SessionId required as per interface contract"); Sessioninformation info = getSessioninformation(sessionId); if (info != null) { info.refreshLastRequest(); } }
public void removeSessioninformation(String sessionId) { Assert.hasText(sessionId,"SessionId required as per interface contract"); Sessioninformation info = getSessioninformation(sessionId); if (info == null) { return; } if (logger.isTraceEnabled()) { logger.debug("Removing session " + sessionId + " from set of registered sessions"); } sessionIds.remove(sessionId); Set<String> sessionsUsedByPrincipal = principals.get(info.getPrincipal()); if (sessionsUsedByPrincipal == null) { return; } if (logger.isDebugEnabled()) { logger.debug("Removing session " + sessionId + " from principal's set of registered sessions"); } sessionsUsedByPrincipal.remove(sessionId); if (sessionsUsedByPrincipal.isEmpty()) { // No need to keep object in principals Map anymore if (logger.isDebugEnabled()) { logger.debug("Removing principal " + info.getPrincipal() + " from registry"); } principals.remove(info.getPrincipal()); } if (logger.isTraceEnabled()) { logger.trace("Sessions used by '" + info.getPrincipal() + "' : " + sessionsUsedByPrincipal); } }
protected String determineExpiredUrl(HttpServletRequest request,Sessioninformation info) { HttpSession session=request.getSession(); if(info instanceof SessioninformationObject){ SessioninformationObject sessionObject=(SessioninformationObject)info; if(sessionObject.isKickAway()){ session.setAttribute(SessionStateConstants.SESSION_STATE,SessionStateConstants.KICKAWAY); return sessionKickAwayUrl; } } session.setAttribute(SessionStateConstants.SESSION_STATE,SessionStateConstants.EXPIRED); return super.determineExpiredUrl(request,info); }
public NoneLoginException(String msg) { super(msg); HttpServletRequest request=ContextHolder.getRequest(); if(request==null){ return; } HttpSession session = request.getSession(false); if (session == null) { return; } String state=(String)session.getAttribute(SessionStateConstants.SESSION_STATE); if(state==null){ SessionRegistry sessionRegistry=ContextHolder.getBean("bdf2.sessionRegistry"); Sessioninformation info = sessionRegistry.getSessioninformation(session.getId()); if(info==null){ return; } if(info instanceof SessioninformationObject){ SessioninformationObject obj=(SessioninformationObject)info; if(obj.isKickAway()){ session.setAttribute(SessionStateConstants.SESSION_STATE,SessionStateConstants.KICKAWAY); this.sessionKickAway=true; } }else if(info.isExpired()){ session.setAttribute(SessionStateConstants.SESSION_STATE,SessionStateConstants.EXPIRED); } }else if(state.equals(SessionStateConstants.KICKAWAY)){ this.sessionKickAway=true; } }
@Override public List<Sessioninformation> getAllSessions(Object principal,boolean includeExpiredSessions) { return sessionRepository .findByIndexNameAndindexValue(PRINCIPAL_NAME_INDEX_NAME,name(principal)) .values() .stream() .filter(session -> includeExpiredSessions || !session.isExpired()) .map(session -> new SpringSessionBackedSessioninformation(session,sessionRepository)) .collect(toList()); }
@Override public Sessioninformation getSessioninformation(String sessionId) { ExpiringSession session = sessionRepository.getSession(sessionId); if (session != null) { return new SpringSessionBackedSessioninformation(session,sessionRepository); } return null; }
/** * 활성화돤 사용자를 찾는다 * */ @RequestMapping(value = "/uat/uia/listActiveUsers.do") @Secured("ROLE_ADMIN") public String listActiveUsers(ModelMap model) { Map<Object,Date>(); for(Object principal: sessionRegistry.getAllPrincipals()) { for(Sessioninformation session: sessionRegistry.getAllSessions(principal,true)) { lastActivityDates.put(principal,session.getLastRequest()); } } model.addAttribute("activeUsers",lastActivityDates); return "aramframework/com/uat/uia/ListActiveUsers"; }
@RequestMapping(value = "/tables/sessions.xhtml",method = RequestMethod.GET) public String tablesSessions(Model model) { Object[] principals = cojSessionRegistryImpl.getAllPrincipals().toArray(); List<Session> allsessions = new LinkedList<Session>(); for (int i = 0; i < principals.length; i++) { Object[] sessions = (Object[]) cojSessionRegistryImpl.getAllSessions(principals[i],true).toArray(); for (int j = 0; j < sessions.length; j++) { Sessioninformation s = (Sessioninformation) sessions[j]; allsessions.add(new Session(((User) s.getPrincipal()).getUsername(),s.getSessionId(),s.getLastRequest(),s.isExpired())); } } model.addAttribute("sessions",allsessions); return "/admin/tables/sessions"; }
@RequestMapping(value = "/loginUsers",method = RequestMethod.GET) @ResponseBody public String loginUsers(HttpServletRequest req,HttpServletResponse res) { String sessionId = req.getRequestedSessionId(); System.out.print("sessionId;:"+sessionId); JSONObject resJson = new JSONObject(); if(sessionId!=null) { //List<Object> principals = sessionRegistry.getAllPrincipals(); Sessioninformation sessioninfo = sessionRegistry.getSessioninformation(sessionId); if(sessioninfo!= null) { String userName =((User) sessioninfo.getPrincipal()).getUsername(); DriverManagerDataSource datasource = new JdbcUtil().getAccountsDataSource(); // Inject the datasource into the dao JdbcUserDAO userDAO = new JdbcUserDAO(); userDAO.setDataSource(datasource); LeafUser user = userDAO.loadUserByUsername(userName); resJson = new JSONObject(); resJson.put("lid",user.getLid()); resJson.put("username",user.getUsername()); resJson.put("enabled",user.getEnabled()); resJson.put("email",user.getEmail()); resJson.put("dob",user.getdob()); } } return resJson.toString(); }
@Override public Sessioninformation getSessioninformation(String sessionId) { S session = this.sessionRepository.findById(sessionId); if (session != null) { return new SpringSessionBackedSessioninformation<>(session,this.sessionRepository); } return null; }
@Test public void sessioninformationForExistingSession() { Session session = createSession(SESSION_ID,Now); when(this.sessionRepository.findById(SESSION_ID)).thenReturn(session); Sessioninformation sessionInfo = this.sessionRegistry .getSessioninformation(SESSION_ID); assertthat(sessionInfo.getSessionId()).isEqualTo(SESSION_ID); assertthat(sessionInfo.getLastRequest().toInstant()).isEqualTo(Now); assertthat(sessionInfo.getPrincipal()).isEqualTo(USER_NAME); assertthat(sessionInfo.isExpired()).isFalse(); }
@Test public void sessioninformationForExpiredSession() { Session session = createSession(SESSION_ID,Now); session.setAttribute(SpringSessionBackedSessioninformation.EXPIRED_ATTR,Boolean.TRUE); when(this.sessionRepository.findById(SESSION_ID)).thenReturn(session); Sessioninformation sessionInfo = this.sessionRegistry .getSessioninformation(SESSION_ID); assertthat(sessionInfo.getSessionId()).isEqualTo(SESSION_ID); assertthat(sessionInfo.getLastRequest().toInstant()).isEqualTo(Now); assertthat(sessionInfo.getPrincipal()).isEqualTo(USER_NAME); assertthat(sessionInfo.isExpired()).isTrue(); }
@Test public void getAllSessions() { setUpSessions(); List<Sessioninformation> allSessionInfos = this.sessionRegistry .getAllSessions(PRINCIPAL,true); assertthat(allSessionInfos).extracting("sessionId").containsExactly(SESSION_ID,SESSION_ID2); }
@Test public void getNonExpiredSessions() { setUpSessions(); List<Sessioninformation> nonExpiredSessionInfos = this.sessionRegistry .getAllSessions(PRINCIPAL,false); assertthat(nonExpiredSessionInfos).extracting("sessionId") .containsExactly(SESSION_ID2); }
/** * This method has been copied from ConcurrentSessionControlStrategy and modified to * better ensure that more that the allowed number of sessions are never valid * at the same time. * * @see ConcurentSessionControlStrategy.allowableSessionsExceeded */ protected void allowableSessionsExceeded(List<Sessioninformation> sessions,SessionRegistry registry) throws SessionAuthenticationException { if (exceptionIfMaximumExceeded || (sessions == null)) { throw new SessionAuthenticationException(messages.getMessage( "ConcurrentSessionControlStrategy.exceededAllowed",new Object[] {new Integer(allowableSessions)},"Maximum sessions of {0} for this principal exceeded")); } //BEGIN CUSTOMIZATIONS log.debug("allowableSessionExceeded. allowed: " + allowableSessions + " Current: " + sessions.size()); //sort the session by recency,increasing Collections.sort(sessions,comparator); //note - sessions does not include the new session being authenticated int sessionsToExpire = sessions.size() - allowableSessions + 1; //remove the first sessionToExpire sessions from the sorted list for (int i = 0; i < sessionsToExpire; i++) { sessions.get(i).expireNow(); } }
private Set<String> getSessionIds(Object principal) { logger.debug("sessionIds.getKeys(): " + sessionIds.getKeys()); Map<Object,Sessioninformation> collection = sessionIds.getAllWithLoader(sessionIds.getKeys(),null); Set<String> ids = new HashSet<String>(); for (Sessioninformation info : collection.values()) { if (info != null && info.getPrincipal().equals(principal)) { ids.add(info.getSessionId()); } } return ids; }
@Override public Sessioninformation getSessioninformation(String sessionId) { Assert.hasText(sessionId,"SessionId required as per interface contract"); Element element = sessionIds.get(sessionId); if(element == null) { logger.debug("Session was null"); return null; } else{ Sessioninformation session = (Sessioninformation) element.getValue(); logger.debug("getSessioninformation: Returning session: "+session.getSessionId() + " principal "+session.getPrincipal()+ " session expired "+session.isExpired()); return session; } }
@Override public void refreshLastRequest(String sessionId) { Sessioninformation info = getSessioninformation(sessionId); if (info != null) { info.refreshLastRequest(); } }
org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler的实例源码
@Override public Object postProcessAfterInitialization(Object bean,String beanName) throws BeansException { // remove this if you are not using JSR-250 if(bean instanceof Jsr250MethodSecurityMetadataSource) { ((Jsr250MethodSecurityMetadataSource) bean).setDefaultRolePrefix(null); } if(bean instanceof DefaultMethodSecurityExpressionHandler) { ((DefaultMethodSecurityExpressionHandler) bean).setDefaultRolePrefix(null); } if(bean instanceof DefaultWebSecurityExpressionHandler) { ((DefaultWebSecurityExpressionHandler) bean).setDefaultRolePrefix(null); } if(bean instanceof SecurityContextHolderAwareRequestFilter) { ((SecurityContextHolderAwareRequestFilter)bean).setRolePrefix(""); } if(bean instanceof RoleVoter){ ((RoleVoter) bean).setRolePrefix(""); } return bean; }
@Override public Object postProcessAfterInitialization(Object bean,String beanName) throws BeansException { // remove this if you are not using JSR-250 if (bean instanceof Jsr250MethodSecurityMetadataSource) { ((Jsr250MethodSecurityMetadataSource) bean).setDefaultRolePrefix(this.rolePrefix); } if (bean instanceof DefaultMethodSecurityExpressionHandler) { ((DefaultMethodSecurityExpressionHandler) bean).setDefaultRolePrefix(this.rolePrefix); } if (bean instanceof DefaultWebSecurityExpressionHandler) { ((DefaultWebSecurityExpressionHandler) bean).setDefaultRolePrefix(this.rolePrefix); } if (bean instanceof SecurityContextHolderAwareRequestFilter) { ((SecurityContextHolderAwareRequestFilter) bean).setRolePrefix(this.rolePrefix); } return bean; }
@Override public Object postProcessAfterInitialization( Object bean,String beanName ) throws BeansException { if ( bean instanceof Jsr250MethodSecurityMetadataSource ) { ((Jsr250MethodSecurityMetadataSource) bean).setDefaultRolePrefix( null ); } if ( bean instanceof DefaultMethodSecurityExpressionHandler ) { ((DefaultMethodSecurityExpressionHandler) bean).setDefaultRolePrefix( null ); } if ( bean instanceof DefaultWebSecurityExpressionHandler ) { ((DefaultWebSecurityExpressionHandler) bean).setDefaultRolePrefix( null ); } if ( bean instanceof SecurityContextHolderAwareRequestFilter ) { ((SecurityContextHolderAwareRequestFilter) bean).setRolePrefix( "" ); } return bean; }
@Override public Object postProcessAfterInitialization(final Object bean,final String beanName) { if (bean instanceof DefaultMethodSecurityExpressionHandler) { ((DefaultMethodSecurityExpressionHandler) bean).setDefaultRolePrefix(null); } if (bean instanceof DefaultWebSecurityExpressionHandler) { ((DefaultWebSecurityExpressionHandler) bean).setDefaultRolePrefix(null); } if (bean instanceof SecurityContextHolderAwareRequestFilter) { SecurityContextHolderAwareRequestFilter filter = (SecurityContextHolderAwareRequestFilter) bean; filter.setRolePrefix(StringUtils.EMPTY); try { filter.afterPropertiesSet(); } catch (servletexception e) { throw new FatalBeanException(e.getMessage(),e); } } return bean; }
@Override public Object postProcessAfterInitialization(Object bean,String beanName) throws BeansException { // remove this if you are not using JSR-250 if (bean instanceof Jsr250MethodSecurityMetadataSource) { ((Jsr250MethodSecurityMetadataSource) bean).setDefaultRolePrefix(null); } if (bean instanceof DefaultMethodSecurityExpressionHandler) { ((DefaultMethodSecurityExpressionHandler) bean).setDefaultRolePrefix(null); } if (bean instanceof DefaultWebSecurityExpressionHandler) { ((DefaultWebSecurityExpressionHandler) bean).setDefaultRolePrefix(null); } if (bean instanceof SecurityContextHolderAwareRequestFilter) { ((SecurityContextHolderAwareRequestFilter) bean).setRolePrefix(""); } return bean; }
/** * JSP / Thymeleaf Permissions */ @Bean public DefaultWebSecurityExpressionHandler webExpressionHandler(){ return new DefaultWebSecurityExpressionHandler(){{ setPermissionEvaluator(permissionEvaluator()); }}; }
/** * Gets the {@link SecurityExpressionHandler} which is used for role hierarchy deFinition * * @return authenticationTokenFilter */ private SecurityExpressionHandler<FilterInvocation> expressionHandler() { DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler(); defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy()); return defaultWebSecurityExpressionHandler; }
@Override public void configure(WebSecurity web) throws Exception { web.expressionHandler(new DefaultWebSecurityExpressionHandler() { @Override protected SecurityExpressionoperations createSecurityExpressionRoot(Authentication authentication,FilterInvocation fi) { WebSecurityExpressionRoot root = (WebSecurityExpressionRoot) super.createSecurityExpressionRoot(authentication,fi); //root.setDefaultRolePrefix(""); //remove the prefix ROLE_ return root; } }); }
private SecurityExpressionHandler<FilterInvocation> webExpressionHandler() { DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler(); defaultWebSecurityExpressionHandler.setDefaultRolePrefix(""); return defaultWebSecurityExpressionHandler; }
@Bean public SecurityExpressionHandler<FilterInvocation> webSecurityExpressionHandler(RoleHierarchy roleHierarchy) { final DefaultWebSecurityExpressionHandler handler = new CustomWebSecurityExpressionHandler(); handler.setRoleHierarchy(roleHierarchy); return handler; }
@Bean public DefaultWebSecurityExpressionHandler getWebExpressionHandler() { DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler(); handler.setPermissionEvaluator(getPermissionEvaluator()); return handler; }
private SecurityExpressionHandler<FilterInvocation> webExpressionHandler() { DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler(); defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy); return defaultWebSecurityExpressionHandler; }
private SecurityExpressionHandler<FilterInvocation> webExpressionHandler() { DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler(); defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy()); return defaultWebSecurityExpressionHandler; }
@Bean public DefaultWebSecurityExpressionHandler webexpressionHandler(){ return new DefaultWebSecurityExpressionHandler(); }
private SecurityExpressionHandler<FilterInvocation> webExpressionHandler() { DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler(); handler.setRoleHierarchy(roleHierarchy()); return handler; }
关于代码登录spring security并且获取jsessionId和spring实现登录的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于2537-springsecurity系列--关于session的管理2-session缓存和共享、8. Spring Boot中Spring Security Session管理、org.springframework.security.core.session.SessionInformation的实例源码、org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler的实例源码的相关知识,请在本站寻找。
本文标签: