如何配置弹簧安全性

Posted

技术标签:

【中文标题】如何配置弹簧安全性【英文标题】:How to configure spring security 【发布时间】:2020-05-19 02:06:05 【问题描述】:

我对 spring-security 的配置有疑问。所以到目前为止我已经做了一些配置,我可以使用所有的 API 和 **GET。但没有其他 API 像 Delete-PUT-Post 一样。 为此,我收到如下错误:

错误是 403.

所以我的配置分为两类:

CorsFilter.java

package com.example.rest.webservices.restfulwebservices.basic.auth;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CorsFilter implements Filter

    @Override
    public void init(FilterConfig filterConfig) throws ServletException
    
    
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
            FilterChain filterChain) throws IOException, ServletException
    
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest) servletRequest;
//        if (request.getMethod().equals("OPTIONS"))
//        
            response.setHeader("Access-Control-Allow-Origin", "http://localhost:4200");
            response.setHeader("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS");
            response.setHeader("Access-Control-Allow-Headers", "*");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Headers",
                    "Content-Type, Authorization, Content-Length, X-Requested-With");
            response.addHeader("Access-Control-Allow-Credentials", "true");
//        
        filterChain.doFilter(servletRequest, servletResponse);
    
    @Override
    public void destroy()
    
    

第二类是:

SpringSecurityConfigurationBasicAuth

package com.example.rest.webservices.restfulwebservices.basic.auth;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.session.SessionManagementFilter;
@Configuration
@EnableWebSecurity
public class SpringSecurityConfigurationBasicAuth extends WebSecurityConfigurerAdapter 

    @Bean
    CorsFilter corsFilter() 
        CorsFilter filter = new CorsFilter();
        return filter;
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
        .addFilterBefore(corsFilter(), SessionManagementFilter.class);
        //http.cors();
        http .csrf()
        .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
            http.authorizeRequests()
                .antMatchers("/**").permitAll()
                    .anyRequest().authenticated()
                    .and()
//            .formLogin().and()
                .httpBasic();
    

我的控制器如下:

项目控制器

package com.example.rest.webservices.restfulwebservices.todo;
import java.net.URI;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
@CrossOrigin(origins="http://localhost:4200")
@RestController
public class ItemController 
    @Autowired
    private ItemService itemService;

    @GetMapping(path = "/users/username/items")
    public List<Item> getAllToDosList(@PathVariable String username)
        return itemService.findAll(username);
    

    @GetMapping(path = "/users/username/item/id")
    public Item getItem(@PathVariable String username, @PathVariable Integer id)
        return itemService.findById(id);
    

    @PutMapping("/users/username/item/id")
    public ResponseEntity<Item> updateItem(@PathVariable String username,
            @PathVariable Integer id, @RequestBody Item item )
        Item updateditem = itemService.saveItem(item);
                return new ResponseEntity<Item>(updateditem, HttpStatus.OK);

    

    @PostMapping("/users/username/item")
    public ResponseEntity<Void> addItem(@PathVariable String username, @RequestBody Item item )
        Item createdItem = itemService.saveItem(item);

                URI uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/id")
                .buildAndExpand(createdItem.getId()).toUri();

                return ResponseEntity.created(uri).build();             
    
    @DeleteMapping(path = "/users/username/item/id")
    public ResponseEntity<Void> removeToDosFromList(@PathVariable String username,
            @PathVariable Integer id)
        Item todo = itemService.deleteToDoById(id);
                if (todo != null)
                
                    return ResponseEntity.noContent().build();
                

                return ResponseEntity.notFound().build();
    

到目前为止,这仅适用于 GET API,请查看类,也许您的想法比我多,因为我缺乏经验。

【问题讨论】:

你能说出你得到的错误吗?在日志中我只能看到调试跟踪,其中一个说 DELETE /error 与 GET /** 不匹配,但本身没有错误。你可以将控制器粘贴到你定义 DELETE /error 路由的位置和你得到响应的 http 状态码? 是的,我会的,谢谢。 【参考方案1】:
            http.authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS,"/**").permitAll()

您在参数中传递了 OPTIONS 方法,用于指定允许哪种方法,只允许 OPTIONS 类型的请求,如果您想允许 get 请求,请使用 GET。如果您想允许所有请求类型,只需传递“/**”作为参数,而不指定任何方法类型。

【讨论】:

我会尝试让您知道,我这样做是因为当我调用 get 时,我使用了预检请求。所以我只是删除了该选项,并且 get 像以前一样工作,但其他 API 现在不起作用我得到 403 但这是因为所有其他请求(不是 OPTIONS)都必须经过身份验证 .antMatchers(HttpMethod.OPTIONS,"/**").permitAll() .anyRequest().authenticated()所以你必须提供你想让请求工作的身份验证方法。不做的话得到403-Forbidden是正常的 @JArgente 你这是什么意思,我不太明白你的意思。现在我已经删除了 OPTIONS 并且我只让 (/) 并且我得到了这个错误,这不应该适用于所有 API,我认为现在的问题是 diff ,看看照片【参考方案2】:

我认为这里的问题是: 你想验证用户调用一些路径吗?

如果答案是否定的,你应该删除这行.anyRequest().authenticated()

如果答案是肯定的,您应该指定要进行身份验证的 url,并定义身份验证方法并使用适当的 Authorization 标头进行调用

【讨论】:

以上是关于如何配置弹簧安全性的主要内容,如果未能解决你的问题,请参考以下文章

如何使百里香弹簧安全命名空间可用?

提供配置弹簧安全的方法?

仅为授权配置弹簧安全性?

如何从环境变量中添加活动弹簧配置文件?

如何强制弹簧只有一个活动配置文件?

如何使用 Maven 配置文件设置弹簧活动配置文件