侧边栏壁纸
  • 累计撰写 31 篇文章
  • 累计创建 6 个标签
  • 累计收到 2 条评论
标签搜索

目 录CONTENT

文章目录

记一次spring boot升级3.2.5后spring security配置文件的修改和认证失败处理

lj2508_com
2024-05-28 / 0 评论 / 0 点赞 / 194 阅读 / 916 字

前景提要。目前系统是在通过/ 根目录时判断用户权限,并根据jwt来返回对应的权限。因集成seata时发现2021版本不支持jdk17。所以直接升级3.2.5

问题描述
通过/认证之后。对中间问写入权限。然后浏览器在后续请求返回403.后台通过日志判断,发现每次请求时都没有认证信息。有个简单点的解决方法,直接去掉/判断或者在每次无权限时都加入信息。pass(后续可能会在里面访问数据库,可能会导致系统缓慢)。通过查看每次的请求,发现sessin会发生变化,在浏览器未重新启动和清理缓存的时候。但同一个session也会有这个问题
image-1716859633466
image-1716859613019
WebSecurityConfig文件对比
升级前

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	 @Override
	    protected void configure(HttpSecurity http) throws Exception {
	        http
	            .authorizeRequests()
	                .antMatchers("/js/**", "/lib/**", "/css/**", "/data/**", "/image/**", "/pages/**").permitAll()
	           .and().csrf().disable().headers().frameOptions().sameOrigin().and()
	            .httpBasic()
	                .disable();
	    }

}

升级后


import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;


@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)  // This replaces @EnableGlobalMethodSecurity
public class WebSecurityConfig {

	@Autowired
	private JWTAuth jwtAuth;	
	
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers("/js/**", "/lib/**", "/css/**", "/data/**", "/images/**", "/pages/**").permitAll()
                .anyRequest().authenticated()
            )
            .csrf(csrf -> csrf.disable()) //关闭csrf
            .sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)) //解决问题的关键
            .headers(headers -> headers.frameOptions(frameOptions -> frameOptions.sameOrigin())) //可以在iframe中访问
            .addFilterBefore(jwtAuth, BasicAuthenticationFilter.class)//加入拦截器
            .httpBasic(httpBasic -> httpBasic.disable()); //关闭http登录框
        
        return http.build();
    }
}

拦截器代码 简易版。因为网站比较简单,所以只有用户id权限标识不一样。仅作为示例来对比,请勿直接使用


import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import com.lj2508.sso.util.JwtUtil;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

/**
 * <p>Title: JWTAuth</p>
 * <p>Description: </p>
 * @author [email protected]
 * @date 2020年5月18日
 */

@Component
public class JWTAuth extends OncePerRequestFilter  {

    @Autowired
    private RedisTemplate<String, String> redis;
    
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        if ( request.getRequestURI().equals("/")) {
            //授权和验证
            Set<GrantedAuthority> authorities = new HashSet<>();
            String id = "";
            try {
                id = JwtUtil.getJwt(request).getId();
            } catch (Exception e) {
                //代表用户未登录
                response.sendRedirect("登录网站");
                return;
            }
            if (id.equals("1"))
                redis.opsForValue().set("1", "ROLE_ADMIN");
            String authName = redis.opsForValue().get(id);
            if (StringUtils.isEmpty(authName))
                authName = "ROLE_USER";
            authorities.add(new SimpleGrantedAuthority(authName));
            UsernamePasswordAuthenticationToken auPasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(id,null, authorities);
            SecurityContextHolder.getContext().setAuthentication(auPasswordAuthenticationToken);
        }
        doFilter(request, response, filterChain);
    }
}

问题解决是修改了
.sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED))
之后。通过设置之后。程序访问正常。仅在/时验证信息,后续可以直接用上下文中获取权限标识

public enum SessionCreationPolicy {

   /**
    * Always create an {@link HttpSession}
    */
   ALWAYS,

   /**
    * Spring Security will never create an {@link HttpSession}, but will use the
    * {@link HttpSession} if it already exists
    */
   NEVER,

   /**
    * Spring Security will only create an {@link HttpSession} if required
    */
   IF_REQUIRED,

   /**
    * Spring Security will never create an {@link HttpSession} and it will never use it
    * to obtain the {@link SecurityContext}
    */
   STATELESS

}
0

评论区