Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Springboot安全性-处理依赖项注入_Java_Spring Boot_Spring Security_Dependency Injection - Fatal编程技术网

Java Springboot安全性-处理依赖项注入

Java Springboot安全性-处理依赖项注入,java,spring-boot,spring-security,dependency-injection,Java,Spring Boot,Spring Security,Dependency Injection,我正在开发一个JavaSpringBootRESTAPI。为了访问端点,用户必须向外部Identity Server服务发送请求,该服务将返回令牌。然后,该令牌将在头授权中发送到此API,该API将在允许请求通过控制器之前检查用户是否在数据库中 我对Java有点陌生,所以我在互联网上用了一些例子来说明如何做到这一点。我到达了一个点,请求进入,被过滤,然后我可以允许它通过或不通过。现在我需要添加检查数据库的部分,以查看用户是否在那里。我对此有些问题 我向gradle添加了以下软件包: boot:

我正在开发一个JavaSpringBootRESTAPI。为了访问端点,用户必须向外部Identity Server服务发送请求,该服务将返回令牌。然后,该令牌将在头授权中发送到此API,该API将在允许请求通过控制器之前检查用户是否在数据库中

我对Java有点陌生,所以我在互联网上用了一些例子来说明如何做到这一点。我到达了一个点,请求进入,被过滤,然后我可以允许它通过或不通过。现在我需要添加检查数据库的部分,以查看用户是否在那里。我对此有些问题

我向gradle添加了以下软件包:

  • boot:springbootstartersecurity
  • io.jsonwebtoken:jjwt:0.7.0(不确定这是否真的有必要,示例中都包含令牌生成,我在这个API中没有这样做)
下面是我在安全包中实现的代码。这是在尝试添加数据库集成之前,因此它会运行并工作:

WebSecurityConfig.java:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.csrf().disable().authorizeRequests()
        .antMatchers(httpMethod.GET, "/user").authenticated()
        .and()
        .addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    // this following one might not be necessary, it was in the example but I don't think it's being used
    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("admin")
            .password("password")
            .roles("ADMIN");

    }
}
JWTAuthenticationFilter.java:

public class JWTAuthenticationFilter extends GenericFilterBean {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
            throws IOException, ServletException {
                
                Authentication authentication = TokenAuthenticationService.getAuthentication((HttpServletRequest) request);
                SecurityContextHolder.getContext().setAuthentication(authentication);
                filterChain.doFilter(request, response);
            }
}
TokenAuthenticationService.java:

public class TokenAuthenticationService {

    static final String SECRET = "mySecret";
    static final String TOKEN_PREFIX = "Bearer";
    static final String HEADER_STRING = "Authorization";

    static Authentication getAuthentication(httpServletRequest request) {
        String token = request.getHeader(HEADER_STRING);
        
        // do a bunch of stuff with the token to get the user Identity

        if (userID != null) {

            // here I need to call a method from a class in gateway, to find this user in the database..
            // if not found I'll return null
            
            return new UsernamePasswordAuthenticationToken(userID, null, Collections.emptyList());
        }

        return null;
    }


}
这就是目前正在运行的代码。但是,我不能从内部调用外部方法
getAuthentication
,因为它是静态的,所以为了调用网关方法,我将它设置为非静态的。 因为我使它不是静态的,所以我必须改变在
JWTAuthenticationFilter
中调用它的方式。我没有直接调用该方法,而是添加了以下行:

TokenAuthenticationService tokenAuthenticationService = new TokenAuthenticationService();
然后使用
tokenAuthenticationService
调用
getAuthentication

之后,我尝试直接调用方法
userGateway.getByUserID
。但是我需要一个瞬间的
UserGateway
。我无法直接初始化
UserGatewayImplementation
的实例。 这不仅违背了我们在这个项目中遵循的依赖注入原则,还需要初始化该类使用的其他东西。其他东西也需要另一个对象等等

因此,我在类中添加了注释
@RequiredArgsConstructor
,并给出了以下内容:

private final UserGateway userGateway;
这样我就可以调用
this.userGateway.getByUserID(userID)

但是,由于我必须创建
TokenAuthenticationService
的实例(因为该方法不再是静态的),并且我向
TokenAuthenticationService
userGateway
)添加了一个属性,它希望我在
JWTAuthenticationFilter
中创建
tokenAuthenticationService
时,将
UserGateway
的实例传递给构造函数

就像以前一样,我不能那样做。因此,我将
@RequiredArgsConstructor
添加到类
JWTAuthenticationFilter
,并赋予它以下属性:

private final TokenAuthenticationService tokenAuthenticationService;
private final JWTAuthenticationFilter jwtAuthenticationFilter;
这样我就可以用它调用
getAuthentication

这当然会导致
WebSecurityConfig
中出现同样的问题。在这方面:

.addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
它创建了一个
JWTAuthenticationFilter
的实例,但现在它希望我将
TokenAuthenticationService
的实例传递给它,因为它具有该属性。 因此,我做了同样的事情,将
@RequiredArgsConstructor
添加到
WebSecurityConfig
类中,并赋予它以下属性:

private final TokenAuthenticationService tokenAuthenticationService;
private final JWTAuthenticationFilter jwtAuthenticationFilter;
然后将此
jwtAuthenticationFilter
传递到
addFilterBefore

执行所有这些操作后,编辑器不再抱怨,但当我尝试运行应用程序时,它会出现以下错误:

***************************
APPLICATION FAILED TO START
***************************
 
Description:
 
Parameter 0 of constructor in (path).security.WebSecurityConfig required a bean of type '(path).security.JWTAuthenticationFilter' that could not be found.
 

Action:
 
Consider defining a bean of type '(path).security.JWTAuthenticationFilter' in your configuration. 
我在谷歌上搜索了这个错误,并试图将
@Bean
添加到
JWTAuthenticationFilter
,添加到
doFilter
,等等,但它不起作用,我并不感到惊讶,因为我是盲目地这么做的。 我非常感谢您的帮助,即使是简短的。最后,我只想能够在
getAuthentication
中从另一个类调用一个方法,检查数据库并查看用户是否在那里。
我显然需要学习更多关于Java和Springboot的知识,但不幸的是,我急于让它发挥作用。

在盲目尝试了很多东西之后,我最终自己找到了答案。我只需要在类
JWTAuthenticationFilter
TokenAuthenticationService
中添加注释
@Component
。现在还不能完全解释,但我会把它留在这里,以防其他人需要。

Lombok与这一切无关。它不“创建对象”,它只是静态地(在编译时)生成一些样板代码,比如构造函数。所有这些都是非常透明的,你可以手工完成。我想如果你不提龙目山,你的问题会有好处的。@MichaelPiefel我明白了。那么,我将删除对Lombok的引用。谢谢。很抱歉,昨天晚上我帮不了你什么忙,但我很高兴你现在已经解决了这个问题。某个地方的某个人需要实例化你的
WebSecurityConfig
类,也就是说,调用它的构造函数。在这个场景中,这就是Spring框架本身。但是当
WebSecurityConfig
构造函数需要一个参数(任何参数)时,Spring需要知道从哪里获得该参数。有不同的方式告诉Spring考虑什么,但是添加<代码> @组件< /代码>是其中之一(即使是最好的,通常);Spring将扫描候选bean的类路径,并考虑所有带有此注释的类(或<代码> @ Service < /Cord>和其他一些)。谢谢,这很有帮助!