nanke1006
2019-01-16 10:57
采纳率: 66.7%
浏览 1.3k
已采纳

关于Spring security登陆后的问题

关于SecurityContextHolder

我在用户登陆成功后,调用以下方法,将用户信息保存在SecurityContextHolder的contextlimian

    protected void makeUser(User userDetails) {
        logger.info("开始记录登陆用户信息!用户名:{}",userDetails.getUsername());
        SecurityContextHolder.getContext().setAuthentication(userDetails);
        HttpSession session = request.getSession(true);
        session.setAttribute(userDetails.getUsername(), SecurityContextHolder.getContext());
        logger.info("记录登陆用户信息完毕!");
    }

然后登陆完成以后,在网页页面上用js进行的跳转到index,此时会获取当前用户信息
调用方法如下:

    /**
     * 获取当前用户
     */
    protected Authentication currentUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        SecurityContext context =(SecurityContext) (request.getSession().getAttribute("SPRING_SECURITY_CONTEXT"));
        return null == authentication? context.getAuthentication() : authentication;
    }

跳转到index的时候
图片说明
此时是能够从上面获取用户的方法中得到用户的信息的
但是一旦我在index界面刷新页面的时候,再次调用上面的方法得到的是匿名用户,相当于处于未登陆的状态。
图片说明

按我的分析,如果登陆成功了,第二次获取不应该获取不到用户信息,第一次获取后,我并没有clearContext,讲道理应该不会获取不到,如果没有登陆成功,则应该是往我设置的登陆页面跳转。
所以我觉得应该是我配置的问题
所以我把配置贴出来,请大佬帮忙看下问题在哪里:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    SecurityFilter securityFilter;

    @Autowired
    UserService userService;

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(getpasswordEncoder());
        auth.eraseCredentials(false);
    }

    private SecuritySuccessHandler getsecuritySuccessHandler() {
        return new SecuritySuccessHandler();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(securityFilter, FilterSecurityInterceptor.class)
            .authorizeRequests()
            .antMatchers("/login", "/dologin","/css/**",
                "/font/*", "/img/**", "/js/**").permitAll()
            .and().formLogin()
            .loginPage("/login").permitAll().successHandler(getsecuritySuccessHandler())
            .and().logout().logoutSuccessUrl("/login")
            .invalidateHttpSession(true)
            .and().rememberMe()//登录后记住用户,下次自动登录,数据库中必须存在名为persistent_logins的表
            .tokenValiditySeconds(1209600)
            .and().csrf().disable();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }

    private PasswordEncoder getpasswordEncoder() {
        return new PasswordEncoder();
    }
}

补充:刷新页面后,我用这个方法SecurityContext context =(SecurityContext) (request.getSession().getAttribute("SPRING_SECURITY_CONTEXT")从session里面也取不到我的用户数据,取出来的是null。

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • nanke1006 2019-01-17 11:36
    已采纳

    查看博客已解决问题,将配置内容改为

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.addFilterBefore(securityFilter, FilterSecurityInterceptor.class)
                .authorizeRequests()
                .antMatchers("/login", "/dologin","/css/**",
                    "/font/*", "/img/**", "/js/**").permitAll()
                .antMatchers("/**").hasAnyRole("USER","ADMIN")
                .anyRequest().authenticated()//就是这一行的差别
                .and().formLogin().successForwardUrl("/index")
                .loginPage("/login").permitAll().successHandler(getsecuritySuccessHandler())
                .failureUrl("/login")
                .and().logout().logoutSuccessUrl("/login")
                .invalidateHttpSession(true)
                .and().rememberMe()//登录后记住用户,下次自动登录,数据库中必须存在名为persistent_logins的表
                .tokenValiditySeconds(1209600)
                .and().csrf().disable();
        }
    

    分析,之前我用的是security4,没有添加这一句可以正常访问与跳转。由于新项目将版本升级至security5,缺失了.anyRequest().authenticated()这一句导致的无法正常的拦截跳转。添加后即可正常运转。官方的文档其实也很难描述清楚这些问题

    打赏 评论

相关推荐 更多相似问题