当前位置: 首页 > 知识库问答 >
问题:

我可以混合使用基本身份验证和JWT令牌身份验证来保护单个Spring Boot项目的API吗?

颛孙钱青
2023-03-14

我是Spring Security方面的新手,正在从事一个Spring Boot项目,该项目使用基本身份验证来保护一些API。我从一个现有的教程代码(Udemy课程)开始,试图使其适应我自己的用例。

在这个项目中,我使用这个安全配置来配置基本身份验证。

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
    private static String REALM = "REAME";
    
    private static final String[] USER_MATCHER = { "/api/utenti/cerca/**"};
    private static final String[] ADMIN_MATCHER = { "/api/utenti/inserisci/**", "/api/utenti/elimina/**" };

    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
            http.csrf().disable()
                .authorizeRequests()
                .antMatchers(USER_MATCHER).hasAnyRole("USER")
                .antMatchers(ADMIN_MATCHER).hasAnyRole("ADMIN")
                .anyRequest().authenticated()
                .and()
                .httpBasic().realmName(REALM).authenticationEntryPoint(getBasicAuthEntryPoint()).and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }
    
    @Bean
    public AuthEntryPoint getBasicAuthEntryPoint()
    {
        return new AuthEntryPoint();
    }

    /* To allow Pre-flight [OPTIONS] request from browser */
    @Override
    public void configure(WebSecurity web) 
    {
        web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder()
    {
        return new BCryptPasswordEncoder();
    };

    @Bean
    @Override
    public UserDetailsService userDetailsService()
    {
        UserBuilder users = User.builder();

        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();

        manager.createUser(users
                .username("ReadUser")
                .password(new BCryptPasswordEncoder().encode("BimBumBam_2018"))
                .roles("USER").build());

        manager.createUser(users
                .username("Admin")
                .password(new BCryptPasswordEncoder().encode("MagicaBula_2018"))
                .roles("USER", "ADMIN").build());

        return manager;
    }
}

所以据我所知:

在这里,it id定义了正常用户可以访问的API列表,以及管理员用户可以访问的API列表:

private static final String[] USER_MATCHER = { "/api/utenti/cerca/**"};
private static final String[] ADMIN_MATCHER = { "/api/utenti/inserisci/**", "/api/utenti/elimina/**" };

在前面的configure()方法中,基本上是说明具有角色USER的登录用户可以访问与USER\u MATCHER匹配的API URL,而具有角色ADMIN的登录用户可以访问具有URL匹配ADMIN\u MATCHER的API。这个解释正确吗?

最后,UserDetailsService bean只定义了两个用户:一个属于用户“组”,另一个属于用户和管理员“组”。

因此,如果我能很好地理解,第一个将是aple,它只能访问具有enpoint URL/API/utenti/cerca/**的API,而第二个将能够访问具有endpointURL/API/utenti/inserisci/**和/API/utenti/elimina的API/**

我的推理正确吗?

现在我的疑问是:在这个项目的控制器类中,我定义了这个方法:

@RestController
@RequestMapping("api/users")
@Log
public class UserController {
    
    @Autowired
    UserService userService;
    
    //@Autowired
    //private BCryptPasswordEncoder passwordEncoder;
    
    //@Autowired
    //private ResourceBundleMessageSource errMessage;
    
    @GetMapping(value = "/test", produces = "application/json")
    public ResponseEntity<String> getTest() throws NotFoundException  {
        
        log.info(String.format("****** getTest() START *******"));
        
        return new ResponseEntity<String>("TEST", HttpStatus.OK);
        
    }
    
    ..............................................................................................................
    ..............................................................................................................
    ..............................................................................................................
}

正如您所看到的,此方法处理对本地主机的GET请求:8019/api/users/testendpoint。

此endpointURL不在与受保护endpoint相关的前两个列表中的任何一个中(它不在USER_MATCHER列表中,也不在ADMIN_MATCHER列表中。所以我预计这个endpoint并不是受保护的,每个人都可以访问。但是使用PostMan执行之前的请求,我收到了这条错误消息:

HTTP Status 401 : Full authentication is required to access this resource

因此,在我看来,基本上,如果这个endpoint不属于任何受保护的endpoint列表,那么它也会以某种方式受到保护(在我看来,至少用户必须经过身份验证(实际上,尝试前一个用户我可以获得预期的输出,因此这应该意味着该endpoint不受用户规则的保护,但它受到未经身份验证访问的保护)。

为什么?也许它取决于前面的configure()方法设置,尤其是这一行?

.anyRequest().authenticated()

在这种情况下,是否可以通过某种方式禁用以实现以下内容:

>

  • 如果被调用的endpoint属于前两个列表(USER_MATCHER和ADMIN_MATCHER)之一--

    如果被调用的endpoint不属于前面的列表之一——

    这种方法有意义,还是我失去了什么?

    我借此机会还想问您另一个信息:您认为是否可以配置此特定项目的Spring Security性,以便使用基本身份验证保护一些特定endpoint,并使用JWT身份验证保护一些其他特定endpoint。

    请进一步说明最后一个问题的原因。该项目是一个微服务,目前由另一个微服务(用于生成JWT令牌)使用,以获取用户信息。(另一个微服务调用此项目的API以接收用户信息,从而生成将在我的应用程序中使用的JWT令牌。这两个微服务之间的通信必须使用基本身份验证)。

    由于此项目包含用于映射与我的DB上的用户相关的表的所有实体类,因此我的想法是也将此项目用于通用用户管理,因此它可以包括以下功能添加全新用户、更改现有用户的信息、获取所有用户的列表、搜索特定用户等等。

    这些新API将受到JWT令牌的保护,因为每个API都可以从在系统上具有不同权限的特定用户类型调用。

    所以我在问,在这种情况下,我是否可以毫无问题地添加2种不同类型的身份验证(检索用户的API的基本身份验证,以便其他微服务可以获取此信息)和所有其他API的JWT身份验证。为新的用户管理微服务创建一个全新的项目是有意义的,还是更好?

  • 共有1个答案

    丰辰沛
    2023-03-14

    因此,如果我能很好地理解,第一个将是aple,它只能访问具有enpoint URL/API/utenti/cerca/**的API,而第二个将能够访问具有endpointURL/API/utenti/inserisci/**和/API/utenti/elimina的API/**

    为什么?也许它取决于前面的configure()方法设置,尤其是这一行?

    是,当使用<代码>时。anyRequest()。authenticated(),任何未匹配的请求都必须经过身份验证。

    如果被html" target="_blank">调用的endpoint不属于前面的列表之一——

    您可以通过执行anyRequest()来实现这一点。permitAll()。但这并不是那么安全,因为您允许访问每个其他endpoint,相反,您应该使用anyRequest()。authenticated()并允许手动访问特定endpoint,如下所示:

    http
                    .authorizeRequests()
                    .antMatchers(USER_MATCHER).hasAnyRole("USER")
                    .antMatchers(ADMIN_MATCHER).hasAnyRole("ADMIN")
                    .antMatchers("/api/users/test").permitAll()
                    .anyRequest().authenticated()
                    ...
    
     类似资料:
    • 我试图让Spring Security的基本身份验证与JWT令牌身份验证同时工作,但没有成功。我已经为web控制台和JWT实现了基本身份验证,以保护许多APIendpoint。下面是我的配置: } 我注意到,我用Order(1)注释的配置是Spring Security选择的配置,而另一个完全被忽略。像上面的配置一样,如果我尝试访问/console/login,我会得到401错误。任何帮助都将不胜

    • null 我的自定义rest筛选器: 上面的内容实际上会导致应用程序启动时出现一个错误:有人能告诉我如何最好地执行此操作吗?pre_auth筛选器是执行此操作的最好方法吗? 编辑 使用Spring-security实现解决方案 希望它能帮助其他人…

    • 我正在使用SpringBoot开发具有微服务架构的Rest Backend。为了保护endpoint,我使用了JWT令牌机制。我正在使用Zuul API网关。 如果请求需要权限(来自JWT的角色),它将被转发到正确的微服务。Zuul api网关的“WebSecurityConfigrerAdapter”如下。 这样,我必须在这个类中编写每个请求授权部分。因此,我希望使用方法级安全性,即“Enabl

    • 有人在springboot应用程序中找到了这样的工作示例吗? /auth控制器,用户在其中提供ActiveDirectory凭据(通过基本身份验证或POST json)并在提供有效AD凭据的情况下接收JWT令牌。不应涉及LDIF文件,Springboot应用程序将根据ldaps://ActiveDirectoryhost: 636endpoint验证凭据 /myapi控制器仅在步骤1(上图)中的有

    • 我在我的Web api项目中使用Swagger: 等等。我们也使用SwaggerUI。工作起来像个符咒。对于生产,我们不希望swagger UI可用,我们希望使用基本身份验证来保护它。Afaik没有现成的此类功能。有没有一种方法可以通过网络api中的某种“黑客”来实现这一点?我可以只为特定的路由或类似的东西注册专用筛选器吗? 感谢你的帮助问候劳琳

    • 我刚刚开始在.NET中开发我的第一个REST API。由于它将是无状态的,我将使用令牌进行身份验证: 基本思想(System.Security.Cryptography): null 检查凭据是否有效(用户名,将哈希密码与db值进行比较) 如果为真,则加密数据对象 对生成的令牌使用HMAC,并将其存储到数据库 将令牌(不带HMAC)返回给用户(cookie/字符串) 对需要身份验证的方法的请求: