栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Springboot拦截器中注入Bean

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Springboot拦截器中注入Bean

今天被人提了个问题——在拦截器(Filter)中注入Bean后拿不到对象(为null),如何避免这个坑?

 废话不多说了,咱们直接看解决方案代码吧!

 首先来看一下拦截器中的内容: 

认证拦截其中配置了,获取用户输入用户名和密码方法,认证成功方法及认证失败处理方法,以及日志入库封装代码;

当认证成功后,记录日志入库的时候,会发现此处的journalService是null,无法获取相对应的Bean对象,

public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {

    private Logger logger = LoggerFactory.getLogger(TokenLoginFilter.class);
    private TokenManager tokenManager;
    private JournalService journalService;
    private RedisTemplate redisTemplate;
    // 权限管理工具,由SpringSecurity封装提供
    private AuthenticationManager authenticationManager;

    public TokenLoginFilter(AuthenticationManager authenticationManager, TokenManager tokenManager, RedisTemplate redisTemplate,JournalService journalService) {
        this.authenticationManager = authenticationManager;
        this.tokenManager = tokenManager;
        this.redisTemplate = redisTemplate;
        this.journalService = journalService;
        this.setPostOnly(false);
    }

    // 1 获取表单提交用户名和密码
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException {
        //获取表单提交数据
        try {
            User user = new ObjectMapper().readValue(request.getInputStream(), User.class);
            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(),user.getPassword(),
                    new ArrayList<>()));
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
    }

    // 2 认证成功调用的方法
    @Override
    protected void successfulAuthentication(HttpServletRequest request,
                                            HttpServletResponse response, FilterChain chain, Authentication authResult)
            throws IOException, ServletException {
    
        insertJournal(user,request);
     
        ResponseUtil.out(response, apiResult);
    }

    // 3  认证失败调用的方法
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed)
            throws IOException, ServletException {
        logger.info("认证登录失败,失败原因:{}",failed.getMessage());
        ApiResult apiResult = new ApiResult();
        apiResult.setResultCode(ApiResponse.FAIL.getResCode());
        apiResult.setMsg("用户名密码错误");
        ResponseUtil.out(response, apiResult);
    }

    @Async
    public void insertJournal(SecurityUser user,HttpServletRequest request) throws BaseException {
        Journal journal = new Journal();
        journal.setCreateTime(new Date());
        journal.setMethod("login");
        journal.setName(user.getUsername());
        journal.setIpAddress(IpUtils.getIp(request));
        journal.setRemark("登录成功");
        journalService.insertSelective(journal);
    }

}

通过上面的代码便是拦截其中注入Bean的操作,此时如果没有任何配置,则注入的Bean全部获取不到对象值,全部为null

接下来我们看解决方案:

次配置类中公共构造函数中会按照系统注入所需要的tokenManager、redisTemplate、defaultPasswordEncoder、userDetailsService、journalServiced对象。

相对应的配置设置会实现商法所说的注入动作,这样即可完成正确的Bean注入操作

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class TokenWebSecurityConfig extends WebSecurityConfigurerAdapter {

    private TokenManager tokenManager;
    private RedisTemplate redisTemplate;
    private DefaultPasswordEncoder defaultPasswordEncoder;
    private UserDetailsService userDetailsService;
    private JournalService journalService;

    @Autowired
    public TokenWebSecurityConfig(UserDetailsService userDetailsService, DefaultPasswordEncoder defaultPasswordEncoder,
                                  TokenManager tokenManager, RedisTemplate redisTemplate,JournalService journalService) {
        this.userDetailsService = userDetailsService;
        this.defaultPasswordEncoder = defaultPasswordEncoder;
        this.tokenManager = tokenManager;
        this.redisTemplate = redisTemplate;
        this.journalService = journalService;
    }

    
    // 设置退出的地址和token,redis操作地址
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors();
        http.exceptionHandling()
                .authenticationEntryPoint(new UnauthEntryPoint()) // 没有权限访问
                .and().csrf().disable()
                .authorizeRequests()
                .anyRequest().authenticated() //任何请求,登录后可以访问
                .and().logout().logoutUrl("/index/logout")//退出路径
                .addLogoutHandler(new TokenLogoutHandler(tokenManager,redisTemplate)).and()
                .addFilter(new TokenLoginFilter(authenticationManager(), tokenManager, redisTemplate,journalService))
                .addFilter(new TokenAuthFilter(authenticationManager(), tokenManager, redisTemplate)).httpBasic();

    }
}

这一步中的关键便是构造函数中为注入Bean赋值,然后配置Filter时注入对象即可。

好了,这样即可完成拦截器中注入Bean操作,觉得有帮助,帮小编点个赞吧!

更多编程内容,请扫码关注《coder练习生》,如果觉得有用,也可赠送作者一杯咖啡

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1006133.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号