2016-05-30 172 views
0

我们有一个使用基本身份验证(用户和密码)的应用程序,我们在数据库中创建了角色,并且工作完美。 现在我们正在迁移使用Login With Amazon,我们还将添加使用Facebook登录。 有没有一种简单的方法来保持我们当前的Spring Security体系结构(尽管我不需要用户密码,但我想保留角色)并添加对使用Amazon进行登录的支持。用亚马逊登录弹簧安全

我注意到有这个项目用于Spring Security with oAuth2 http://projects.spring.io/spring-security-oauth/我不清楚这是干嘛的。

回答

0

Spring oAuth的文档非常糟糕,但是他们提供的examples是可行的,如果你知道Spring Security的解决方法。

我想在此标记,使用oAuth 2进行用户认证isn't recommended,并且您应该坚持支持Open ID Connect的提供商。我不清楚快速浏览Login With Amazon如果是OIDC或者简单的oAuth2,但是无论哪种方式,您都可以使用他们的SDK来实现您要查找的内容。

绝对有可能使用Spring oAuth来设置oAuth 2的登录,也可能是OIDC,但我总是最终滚动我自己的解决方案,因为我觉得它更简单。

我打算专注于在亚马逊网站上登录,但使用Facebook登录应该非常相似。

有四件事情你需要做的:

  1. 加入亚马逊登录到您的网站
  2. 实现在用户配置文件
  3. 存储用户的外部ID支持实现控制器处理JWT令牌用户和“记录”
  4. 调用新的控制器,一旦用户在

已经登录第一个应该是相当容易的,详细的Amazon's documentation

第二个完全取决于你,因为它取决于你的数据库解决方案,只需将属性amazonId添加到用户配置文件。

第三个会是这个样子:

@Controller 
public class OidcController { 

    @Autowired 
    private ObjectMapper objectMapper; 

    @RequestMapping("/login/amazon") 
    public String handleAmazonOidc(@RequestParam String access_token) { 
     // verify that the access token belongs to us 
     Content c = Request.Get("https://api.amazon.com/auth/o2/tokeninfo?access_token=" + URLEncoder.encode(access_token, "UTF-8")) 
         .execute() 
         .returnContent(); 

     Map<String, Object> m = (Map<String, Object>)objectMapper.readValue(c.toString(), Map.class); 
     if (!"YOUR-CLIENT-ID".equals(m.get("aud"))) { 
      // the access token does not belong to us 
      throw new InvalidTokenException("Invalid token"); 
     } 

     // Get the user ID from Amazon and get the corresponding user on our end 
     m = new ObjectMapper().readValue(c.toString(), new TypeReference>(){}); 
     String amazonUserId = m.get("user_id"); 

     User user = getUserFromAmazonId(amazonUserId); 
     if (user == null) { 
      // User needs to register first 
      return "redirect:/register"; 
     } 

     // Authenticate the user in the current security context 
     PreAuthenticatedAuthenticationToken token = new PreAuthenticatedAuthenticationToken(user, token, user.getAuthorities()); 
     SecurityContextHolder.getContext().setAuthentication(token); 

     // Redirect the user to the front page 
     return "redirect:/"; 
    } 
} 

第四个是简单,只需将用户重定向在UI回调:

amazon.Login.authorize(options, 'https://www.example.com/login/amazon'); 

现在,你在一些麻烦,因为你已经有数据库中的用户没有找到亚马逊用户ID,所以你可能必须同时运行两种身份验证方案,并允许用户与亚马逊连接使用用户名和密码登录。修改上述控制器以在当前用户配置文件中插入Amazon用户标识,而不是将其设置在安全上下文中应该相当简单。

+0

非常感谢您的回复Raniz。在这一行 PreAuthenticatedAuthenticationToken token = new PreAuthenticatedAuthenticationToken(user,token,user.getAuthorities()); 你是怎么知道我们需要PreAuthenticatedAuthenticationToken的?围绕这门课有一些很好的文档/例子。 我认为这正是我所期待的。第二个参数是令牌,你的意思是oAuTh访问令牌?我应该在那里通过null。 – momo

+0

小问题,使用oAuth进行身份验证有什么问题。在这种情况下,如果我不这样做,认证的正确方法是什么? (我不打算使用用户/密码,只用亚马逊登录) – momo

+0

问题是这样的:“由于认证通常发生在发放访问令牌之前,因此很容易考虑接收任何类型的访问令牌证明已经发生了这样的认证。“只是获取访问令牌并不能证明用户在访问令牌被发布时涉及 - 它可能已经与刷新令牌一起发出,在这种情况下用户不在场。来自OIDC的ID令牌包含可用于验证用户是否在场的信息。阅读我链接的文章的* Common Pitfalls *部分(以及下一个关于OIDC)以了解更多信息 – Raniz