ROJDAR 2023-02-08 11:57 采纳率: 33.3%
浏览 180

springSecurity报错栈溢出如何解决?

springSecurity报错java.lang.StackOverflowError: null,原因是ProviderManager.authenticate(Authentication authentication)方法中,provder和toTest一直不匹配,导致循环调用。

两者不匹配导致一直无法进入if中:

img

在方法中又一次调用authenticate()方法,以此循环导致栈溢出:

img

我的配置:

package com.rojdar.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @ClassName: WebSecurityConfig
 * @author: ROJDAR
 * @CreateDate: 2023/2/7 9:56
 * @Description: 配置security第二步:创建securityWEB配置类 用于管理security的拦截路径 放行路径 密码解码器等
 **/
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
    @Autowired
    private UserDetailsService userDetailsService;
    /**
     * 创建密码编码器
     * 在进行认证操作的时候就会根据设置的编码器将传入的密码加密后和数据库保存的密码进行比对
     *
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        return encoder;
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setPasswordEncoder(passwordEncoder());
        provider.setUserDetailsService(userDetailsService);
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
        auth.authenticationProvider(provider);
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManagerBean();
    }


    /**
     * 3.授权规则配置
     * - anyRequest():任何请求
     * - antMatchers(“/path”) :匹配某个资源路径
     * - authenticationed() : 保护URL需要登录访问anyRequest().authenticationed()
     * - permitAll():指定url无需保护(放行)一般用户静态资源antMatchers(“/path”).permitAll()
     * - hasRole(String role):某个资源需要用户拥有什么样的role才能访问
     * 例:antMatchers(“/path”).hasRole(“admin”)
     * - hasAuthority**(String authority):某个资源需要用户拥有什么样的权限才能访问
     * 例:antMatchers(“/path”).hasAuthority(“admin”)
     * - (String ..…roles):某个资源拥有指定角色中的一个就能访问
     * - hasAnyAuthority(String ..… authorities):某个资源拥有指定权限中的一个就能访问
     * - access(String attribute):该方法使用SPEL表达式,可以创建复杂的限制
     * - hasIpAddress(String ip):拥有什么样的ip或子网可以访问该资源
     * 权限的设置是按照`从上到下的优先级`。及满足了最开始的权限设置,那么后面的设置就不起作用了
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                /*
                匹配到的请求 放行
                 */
                .antMatchers("/login").anonymous()
                /*
                所有请求 需要认证  当前请求进来时 检查是否放行是从上到下进行的 上面已经配置了/login放行 哪怕下面配置了
                所有请求都需要认证但是/login请求还是会放行
                 */
                .anyRequest().authenticated()
                /*
                关闭跨域检查
                 */
                .and().csrf().disable()
                /*
                登出  放行
                 */
                .logout().permitAll();
        // 添加JWT filter 到 UsernamePasswordAuthenticationFilter 之前
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
    }
}


package com.rojdar.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.rojdar.domain.TLogin;
import com.rojdar.service.LoginService;
import com.rojdar.utils.AjaxResult;
import com.rojdar.utils.HttpStatus;
import com.rojdar.utils.JwtUtils;
import com.rojdar.utils.RedisOperator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.HashMap;

/**
 * @ClassName: LoginServiceImpl
 * @author: ROJDAR
 * @CreateDate: 2023/2/7 11:07
 * @Description: 登录实现
 **/
@Service
public class LoginServiceImpl implements LoginService {
    //认证管理器
    @Resource
    private AuthenticationManager authenticationManager;

    @Autowired
    private RedisOperator redisOperator;

    /**
     * 自定义实现登录过程
     *
     * @param user
     * @return
     */
    @Override
    public AjaxResult login(TLogin user) {
        /*
         * 创建UsernamePasswordAuthenticationToken将用户信息拿去认证管理器认证
         */
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);

        /*
        认证结果返回后 如果认证失败则return 认证成功就创建jwt令牌带回
         */
        if (StringUtils.isEmpty(authenticate)) {
            return AjaxResult.error("用户名称或者密码错误");
        }

        TLogin DBUser = (TLogin) authenticate.getPrincipal();
        HashMap<String, Object> map = new HashMap<>(1);
        map.put(JwtUtils.DETAILS_USER_ID, DBUser.getId());
        String token = JwtUtils.createToken(map);

        redisOperator.set("login:"+DBUser.getId(), JSONObject.toJSONString(DBUser),60 * 30);
        return new AjaxResult(HttpStatus.SUCCESS, "登录成功").put("token", token);
    }
}


  • 写回答

2条回答 默认 最新

  • a1767028198 2023-02-08 13:06
    关注

    正常是第一次的对象有parent,进入到parent的时候,它的parent是null

    评论

报告相同问题?

问题事件

  • 创建了问题 2月8日

悬赏问题

  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等
  • ¥15 matlab 用yalmip搭建模型,cplex求解,线性化处理的方法
  • ¥15 qt6.6.3 基于百度云的语音识别 不会改
  • ¥15 关于#目标检测#的问题:大概就是类似后台自动检测某下架商品的库存,在他监测到该商品上架并且可以购买的瞬间点击立即购买下单
  • ¥15 神经网络怎么把隐含层变量融合到损失函数中?
  • ¥15 lingo18勾选global solver求解使用的算法
  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行
  • ¥20 测距传感器数据手册i2c