前景提要
HDC调试需求开发(15万预算),能者速来!>>>
最近学习springboot,写了一个demo,写到一个页面的时候,想实现一个效果,就是如果登录认证了就显示用户名,没有认证就显示一个登录的超链接,于是我引入了springsecurity整合thymeleaf的一个jar,页面代码如下: <span class ="navbar-brand" sec :authorize ="isAnonymous()" > 未登录,点击 <a th :href ="@{/login}" > 登录 </a> </span> <div sec :authorize ="isAuthenticated()" > <li class ="dropdown" > <a class ="dropdown-toggle navbar-brand img-user-pointer" data-toggle ="dropdown" > <!--<img src="assets/images/default-user.jpg" class="img-circle img-user-size"> --> <span class ="glyphicon glyphicon-user" ></span> <span th :text ="${#authentication.name}" ></span> <b class ="caret" ></b> </a> <ul class ="dropdown-menu" > <li role ="presentation" > <a role ="menuitem" tabindex ="-1" href ="#" ><span class ="glyphicon glyphicon-user" ></span> 个人信息 </a> </li> <li role ="presentation" > <a role ="menuitem" tabindex ="-1" href ="logout" ><span class ="glyphicon glyphicon-off" ></span> 登 出 </a> </li> </ul> </li> </div>
引用两个sec的属性,但页面却两个都没有生效,百思不得其解,后来看了 thymeleaf-extras-springsecurity5
这个包的部分源码,发现在解析属性的时候会通过 SecurityContextHolder.getContext()
方式获取SpringSecurity的上下文用户信息,一下为部分源码: static Authentication getAuthenticationObject() { SecurityContext securityContext = SecurityContextHolder.getContext() ; if (securityContext == null ) { if (SpringSecurityContextUtils.logger.isTraceEnabled()) { SpringSecurityContextUtils.logger.trace( "[THYMELEAF][{}] No security context found, no authentication object returned." , new Object[]{TemplateEngine.threadIndex()}) ; } return null; } else { return securityContext.getAuthentication() ; } }
打断点的时候发现获取的auth一直为null: protected boolean isVisible(ITemplateContext context , IProcessableElementTag tag , AttributeName attributeName , String attributeValue) { String attrValue = attributeValue == null ? null : attributeValue.trim() ; if (attrValue != null && attrValue.length() != 0 ) { Authentication authentication = AuthUtils.getAuthenticationObject(context) ; return authentication == null ? false : AuthUtils.authorizeUsingAccessExpression(context , attrValue , authentication) ; } else { return false; } }
所以页面没有解析成功。
于是我在controller里尝试输出我的登录用户信息,经过一番鼓捣,发现,当我请求的页面配置过滤不需要进行安全验证时,就算我进行了登录也无法获取用户信息,只有配置必须安全验证然后登录才能正常获取auth用户信息,才能使用sec属性标签,反之则页面sec标签属性无法生效
以下为我的SecurityConfig配置: package com.example.demo.security ; import com.example.demo.security.handler.LoginFailureHandler ; import com.example.demo.security.handler.LoginSuccessHandler ; import com.example.demo.service.UserService ; import org.springframework.beans.factory.annotation. Autowired ; import org.springframework.beans.factory.annotation. Value ; import org.springframework.context.annotation. Bean ; import org.springframework.context.annotation. Configuration ; import org.springframework.security.authentication.AuthenticationManager ; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder ; 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. EnableWebSecurity ; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter ; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder ; import org.springframework.util.StringUtils ; // 使用 security 实现登录 @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { // 跳过安全验证的路径 @Value ( "${auth.no_security_path}" ) private String no_security_path ; @Autowired private UserService userService ; @Bean public BCryptPasswordEncoder passwordEncoder (){ return new BCryptPasswordEncoder() ; } /** * 解决 AuthenticationManager 无法注入问题 * @return * @throws Exception */ @Bean @Override public AuthenticationManager authenticationManagerBean () throws Exception { return super .authenticationManagerBean() ; } @Override public void configure (WebSecurity web) throws Exception { if (StringUtils. hasText ( no_security_path )){ String[] path = no_security_path .split( "," ) ; web.ignoring().antMatchers(path) ; } } @Override protected void configure (HttpSecurity http) throws Exception { //csrf 安全 http.csrf().disable().authorizeRequests() .anyRequest().authenticated() .and() .formLogin().loginPage( "/login" ).usernameParameter( "username" ).passwordParameter( "password" ) .failureHandler( new LoginFailureHandler()).successHandler( new LoginSuccessHandler()) .and() .logout().logoutUrl( "/logout" ).logoutSuccessUrl( "/login" ).permitAll().invalidateHttpSession( true ) .and() .sessionManagement() .invalidSessionUrl( "/login" ) ; } @Override protected void configure (AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService( userService ).passwordEncoder(passwordEncoder()) ; } }
请教一下大家,我应该怎么让页面在不需要必须安全验证的情况下能获取用户信息使sec标签属性生效。