从 Spring 控制器调用安全方法,无需身份验证

Posted

技术标签:

【中文标题】从 Spring 控制器调用安全方法,无需身份验证【英文标题】:Invoke secured method from Spring controller without authentication 【发布时间】:2017-12-19 21:52:29 【问题描述】:

我正在使用 Spring Boot 1.5.4、Spring Data REST、Spring Security。我创建了一个 @Controller 映射到不需要身份验证的特定路径,因为它从 sms 网关用于报告传入文本。

所以我只需要创建一个控制器来读取这些参数,然后将文本保存在数据库中。这就是问题所在。为了存储数据,我使用受保护的存储库,而在控制器中我没有任何安全措施(实际上我不能要求提供者保护它的调用)。

我尝试以编程方式设置身份验证上下文,但似乎不起作用:

@Controller
@RequestMapping(path = "/api/v1/inbound")
@Transactional
public class InboundSmsController 
    private Logger log = LogManager.getLogger();

 @RequestMapping(method = RequestMethod.POST, path = "/incomingSms", produces = "text/plain;charset=ISO-8859-1")
public ResponseEntity<?> incomingSms(@RequestParam(name = "Sender", required = true) String sender,
        @RequestParam(name = "Destination", required = true) String destination,
        @RequestParam(name = "Timestamp", required = true) String timestamp,
        @RequestParam(name = "Body", required = true) String body) 

    log.info(String.format("Text received from %s to %s at %s with content: %s", sender, destination, timestamp, body));
    setupAuthentication();

    try                        
        int transitsWithSameTextToday = transitCertificateRepository.countByTextAndDate(body, Instant.now()); //This is the method that raises an Auth exception
....
....
 finally()
   clearAuthentication();



SecurityContext context;

/**
 * Set in the actual context the authentication for the system user
 */
private void setupAuthentication() 
    context = SecurityContextHolder.createEmptyContext();
    Collection<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_ADMIN");
    Authentication authentication = new UsernamePasswordAuthenticationToken("system", "ROLE_ADMIN", authorities);
    context.setAuthentication(authentication);


private void clearAuthentication() 
    context.setAuthentication(null);

方法countByTextAndDate注解为@PreAuthorize("isAuthenticated()")

我很惊讶还设置了身份验证上下文我有这个错误。难道我做错了什么?这是实现目标的最佳方式吗?

我不想用 @PermitAll 注释我的方法,因为 Spring Data REST 也公开了该方法,我不希望任何人都可以使用它。

【问题讨论】:

只需像往常一样设置安全性(这样您就有了身份验证、匿名身份但仍然是授权)并为该特定方编写安全规则。喜欢@PreAuthorize("isAuthenticated() || hasIpAddress(&lt;the-explicit-ip-address-from-the-sms-gateway&gt;)") 【参考方案1】:

您正在寻找AccessDecisionManager 的RunAsManager。这是可以帮助您解决此问题的链接: http://www.baeldung.com/spring-security-run-as-auth

编码愉快!!!

【讨论】:

以上是关于从 Spring 控制器调用安全方法,无需身份验证的主要内容,如果未能解决你的问题,请参考以下文章

如何从控制器调用身份验证 - 弹簧安全核心插件

Spring自定义身份验证过滤器和提供者不调用控制器方法

spring AOP 和自定义注解进行身份验证

无需身份验证的安全 Rails 3 MultiStep 订单的最佳方法

从安全上下文中获取当前经过身份验证的用户作为 Spring Cache 的密钥

Spring(引导)具有允许资源的安全预身份验证仍然经过身份验证