使用Spring和Spring security访问拒绝和允许功能

使用Spring和Spring security访问拒绝和允许功能,spring,spring-boot,spring-security,Spring,Spring Boot,Spring Security,目前,我正在尝试使用SpringMVC和SpringBoot以及SpringSecurity实现身份验证示例。在我的示例应用程序中,我试图做的是——在一个URL的头中发送一个身份验证令牌。我需要从URL获取此身份验证令牌并进行解码。如果用户名和密码匹配,则只需将控件转移到端点“api/getStudent/v1”或类似的内容。否则从那里只需要给出否定的回答 为此,我目前尝试使用spring security的身份验证提供程序。但它不适合从请求头中获取令牌。这里我的困惑是,从SpringSecur

目前,我正在尝试使用SpringMVC和SpringBoot以及SpringSecurity实现身份验证示例。在我的示例应用程序中,我试图做的是——在一个URL的头中发送一个身份验证令牌。我需要从URL获取此身份验证令牌并进行解码。如果用户名和密码匹配,则只需将控件转移到端点“api/getStudent/v1”或类似的内容。否则从那里只需要给出否定的回答


为此,我目前尝试使用spring security的身份验证提供程序。但它不适合从请求头中获取令牌。这里我的困惑是,从SpringSecurity我必须在这里实现哪种方法?有谁能建议一种标准的实施方式吗?或者任何此类实现的文档?

似乎您正在使用REST API,您可以使用类似于此的JWT和自定义筛选器()

似乎您正在使用REST API,您可以使用类似于此的JWT和自定义筛选器()

您只需创建一个自定义安全过滤器,并在spring security BasicAuthenticationFilter之前插入此过滤器。示例代码-

public class CustomAuthenticationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain) throws ServletException, IOException {

        String authHeader = request.getHeaders("Authorization");
        //Decode the authHeader

        //Validate the authHeader with your username & password
        if(invalid) {
            //throw exception and abort processing
        }
        filterChain.doFilter(request, response);
    }
}
现在,您可以创建bean,或者将其作为
@component
来创建,这样spring就会为您创建bean

在您的安全配置中,添加以下内容-

@Configuration
public class CustomWebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.addFilterAfter(new CustomAuthenticationFilter(), BasicAuthenticationFilter.class);
    }
}

您只需创建一个自定义安全过滤器,并在spring security BasicAuthenticationFilter之前插入此过滤器。示例代码-

public class CustomAuthenticationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain) throws ServletException, IOException {

        String authHeader = request.getHeaders("Authorization");
        //Decode the authHeader

        //Validate the authHeader with your username & password
        if(invalid) {
            //throw exception and abort processing
        }
        filterChain.doFilter(request, response);
    }
}
现在,您可以创建bean,或者将其作为
@component
来创建,这样spring就会为您创建bean

在您的安全配置中,添加以下内容-

@Configuration
public class CustomWebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.addFilterAfter(new CustomAuthenticationFilter(), BasicAuthenticationFilter.class);
    }
}
我正在一个URL的头中发送一个身份验证令牌。我需要 从URL获取此身份验证令牌并解码。如果用户名和 密码匹配

通常,使用令牌进行身份验证的目的是摆脱用户名和密码检查

Spring Security开箱即用支持的基本HTTP身份验证假定在HTTP头中传递base64编码的用户名和密码:例如
授权:基本QWXHZGRPBJPCGVU2VZYW1L
(base64编码
阿拉丁:OpenSesame

如果您仍然需要以不同的方式从令牌中提取用户名和密码,请考虑下面的示例。

考虑到您有以下REST控制器:

@RestController
public class TestRestController {

    @GetMapping("/api/getStudent/v1")
    public String helloWorld() {
        return "Hello, World!";
    }

    @GetMapping("/info")
    public String test() {
        return "Test";
    }
}
为了使端点
/api/getStudent/v1
受保护且
/info
公开,并从HTTP请求头提取主体和凭据,您需要实现自定义:

此筛选器必须从传入的令牌头中提取主体和凭据,并尝试使用Spring Security进行身份验证

接下来,您必须创建此自定义筛选器的实例,并配置Spring Security以在安全筛选器链中添加筛选器(
.addFilterBefore(authenticationFilter(),UsernamePasswordAuthenticationFilter.class)
):

让筛选器了解Spring安全性非常重要:
authenticationFilter.setAuthenticationManager(authenticationManagerBean())

您可以通过传递:例如,
新AntPathRequestMatcher(“/api/**”
)来配置要通过身份验证保护的端点

对于测试,您可以使用用户名
test
、密码
test
和权限
admin
在内存中创建和测试用户:

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    //...

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

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("test")
            .password(passwordEncoder().encode("test"))
            .authorities("admin");
    }
}
运行应用程序并尝试在不进行身份验证的情况下访问公共终结点:

curl -i http://localhost:8080/info
HTTP/1.1 200 
Test
curl -i http://localhost:8080/api/getStudent/v1 
HTTP/1.1 401
未经身份验证的受保护终结点:

curl -i http://localhost:8080/info
HTTP/1.1 200 
Test
curl -i http://localhost:8080/api/getStudent/v1 
HTTP/1.1 401
没有无效令牌的受保护终结点:

curl -i http://localhost:8080/api/getStudent/v1 -H 'token: not_valid'
HTTP/1.1 401
curl -i http://localhost:8080/api/getStudent/v1 -H 'token: test'
HTTP/1.1 200 
Hello, World!
最后是具有有效令牌的受保护端点:

curl -i http://localhost:8080/api/getStudent/v1 -H 'token: not_valid'
HTTP/1.1 401
curl -i http://localhost:8080/api/getStudent/v1 -H 'token: test'
HTTP/1.1 200 
Hello, World!
我正在一个URL的头中发送一个身份验证令牌。我需要 从URL获取此身份验证令牌并解码。如果用户名和 密码匹配

通常,使用令牌进行身份验证的目的是摆脱用户名和密码检查

Spring Security开箱即用支持的基本HTTP身份验证假定在HTTP头中传递base64编码的用户名和密码:例如
授权:基本QWXHZGRPBJPCGVU2VZYW1L
(base64编码
阿拉丁:OpenSesame

如果您仍然需要以不同的方式从令牌中提取用户名和密码,请考虑下面的示例。

考虑到您有以下REST控制器:

@RestController
public class TestRestController {

    @GetMapping("/api/getStudent/v1")
    public String helloWorld() {
        return "Hello, World!";
    }

    @GetMapping("/info")
    public String test() {
        return "Test";
    }
}
为了使端点
/api/getStudent/v1
受保护且
/info
公开,并从HTTP请求头提取主体和凭据,您需要实现自定义:

此筛选器必须从传入的令牌头中提取主体和凭据,并尝试使用Spring Security进行身份验证

接下来,您必须创建此自定义筛选器的实例,并配置Spring Security以在安全筛选器链中添加筛选器(
.addFilterBefore(authenticationFilter(),UsernamePasswordAuthenticationFilter.class)
):

让筛选器了解Spring安全性非常重要:
authenticationFilter.setAuthenticationManager(authenticationManagerBean())

您可以通过传递:例如,
新AntPathRequestMatcher(“/api/**”
)来配置要通过身份验证保护的端点

对于测试,您可以使用用户名
test
、密码
test
和权限
admin
在内存中创建和测试用户:

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    //...

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

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("test")
            .password(passwordEncoder().encode("test"))
            .authorities("admin");
    }
}
运行应用程序并尝试在不进行身份验证的情况下访问公共终结点:

curl -i http://localhost:8080/info
HTTP/1.1 200 
Test
curl -i http://localhost:8080/api/getStudent/v1 
HTTP/1.1 401
未经身份验证的受保护终结点:

curl -i http://localhost:8080/info
HTTP/1.1 200 
Test
curl -i http://localhost:8080/api/getStudent/v1 
HTTP/1.1 401
没有无效令牌的受保护终结点:

curl -i http://localhost:8080/api/getStudent/v1 -H 'token: not_valid'
HTTP/1.1 401
curl -i http://localhost:8080/api/getStudent/v1 -H 'token: test'
HTTP/1.1 200 
Hello, World!
最后是具有有效令牌的受保护端点:

curl -i http://localhost:8080/api/getStudent/v1 -H 'token: not_valid'
HTTP/1.1 401
curl -i http://localhost:8080/api/getStudent/v1 -H 'token: test'
HTTP/1.1 200 
Hello, World!

您可以尝试以下方法。我在这里使用了JWT身份验证。根据你的问题,你可以