Spring Security的4与第三方认证令牌 [英] Spring Security 4 with third party authentication token

查看:1403
本文介绍了Spring Security的4与第三方认证令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经做了很多关于这项研究,并有吨的例子,但我的选择不知所措,但我已经把一些code一起做我想做的。

I've been doing a lot of research on this, and there are tons of examples, but I am overwhelmed by the choices, but I have put together some code together to do what I want.

我有一个Apache的负载平衡器重新引导我到一个登录页面,我们OpenAM 10.当我去 https://portal.mydomain.com/myapp <​​/A>我重定向到:
<一href=\"https://sso.mydomain.net:9443/sso/UI/Login?module=AGMAuth&goto=https%3A%2F%2Fvmlb.mydomain.net%3A443%2Fmyapp\" rel=\"nofollow\">https://sso.mydomain.net:9443/sso/UI/Login?module=AGMAuth&goto=https%3A%2F%2Fvmlb.mydomain.net%3A443%2Fmyapp

I have a Apache Load Balancer which re-directs me to a login page for our OpenAM 10. When I go to https://portal.mydomain.com/myapp I get redirected to: https://sso.mydomain.net:9443/sso/UI/Login?module=AGMAuth&goto=https%3A%2F%2Fvmlb.mydomain.net%3A443%2Fmyapp

这是我的登录页,我要求输入用户名和密码,我回来的令牌,看起来像(AQIC5wM2LY4Sfcyl9raxhA​​-xBE14_4QBbkjXi-rFn43PMpc。 AAJTSQACMDE。的)到一个cookie。从前端,我可以从cookie令牌,我可以将其添加到请求头每次调用我的后端是一个REST风格的用SpringMVC后端。

This is my login page, I am asked for a username and password, and I get back a token that looks like (AQIC5wM2LY4Sfcyl9raxhA-xBE14_4QBbkjXi-rFn43PMpc.AAJTSQACMDE.) into a cookie. From the front-end, I can get the token from the cookie, I can add it to the request header for every call to my back-end which is a SpringMVC RESTful back-end.

只是一个供参考的,我知道该怎么称呼一个OpenAM的RESTful API,传递令牌并取回用户名和其他的一些信息。角色不是保存在OpenAM。如果我的REST风格的Web服务后端,我称之为OpenAM与令牌......如果我不回来任何数据,那么我想回到我的自定义验证的登录页面:<一href=\"https://sso.mydomain.net:9443/sso/UI/Login?module=AGMAuth&goto=https%3A%2F%2Fvmlb.mydomain.net%3A443%2Fmyapp\" rel=\"nofollow\">https://sso.mydomain.net:9443/sso/UI/Login?module=AGMAuth&goto=https%3A%2F%2Fvmlb.mydomain.net%3A443%2Fmyapp

Just an FYI, I know how to call an OpenAM RESTful api, passing in that token and getting back the username and some other information. Roles are not kept in OpenAM. If in the back-end of my RESTful web-services, I call OpenAM with the token ... if I do not get back any data, then I want to go back to my custom authentication login page: https://sso.mydomain.net:9443/sso/UI/Login?module=AGMAuth&goto=https%3A%2F%2Fvmlb.mydomain.net%3A443%2Fmyapp

下面是我保护的URL的一个控制器:

Here is the controller of one of my secured URL's:

@RequestMapping(value = "/trialId/{trialId}", method = RequestMethod.GET, headers = "Accept=application/json")
public @ResponseBody TrialEntity getTrialById(@PathVariable("trialId") long trialId)
{
    Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    System.out.println("TrialController: getTrialById: principal");

    UserAccountEntity user = null;
    if (principal instanceof UserAccountEntity)
    {
        user = ((UserAccountEntity) principal);
    }

    TrialEntity trialEntity = service.getById(trialId);
    System.out.println("TrialController: retrieveTrial: trialEntity=" + trialEntity);
    return trialEntity;
}

我是否需要有充分的安全网址试图获得获得本金?

Do I need to have every secure URL try to get get principal?

现在这里是我的弹簧security.xml文件的安全性文件。它可能不是正确的,但它是我起步的地方:

Now here is my spring-security.XML security file. It may not be correct, but it's where I started:

<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd">

<http realm="Protected API" 
    use-expressions="true"                     
    create-session="stateless" 
    entry-point-ref="unauthorizedEntryPoint" 
    authentication-manager-ref="restAuthenticationManager">

    <custom-filter ref="authenticationTokenProcessingFilter" position="FORM_LOGIN_FILTER" />
     <intercept-url pattern="/corelabs" access="permitAll" />
    <intercept-url pattern="/sponsors" access="permitAll" />
    <intercept-url pattern="/trials/trialId/**" access="hasRole('trialAdmin')" />
    <intercept-url pattern="/subjects" access="hasRole('siteSender') and hasRole('trialManager')" />
</http>

<authentication-manager>
  <authentication-provider ref="customAuthenticationProvider"/>
</authentication-manager>   

 <beans:bean id="customUserDetailsService" class="com.agmednet.server.security.CustomUserDetailsService" />

</beans:beans>

现在这里是后端的一些安全code。这是code可以追溯到数据库基础上的用户名来获取用户的详细信息,我也可以加载角色该用户。我从Spring Security的4例子中的一个得到这个。

Now here is some security code on the back-end. This is the code that goes back to the database to get user details based on the username, and I can also load the roles for this user. I got this from one of the Spring Security 4 examples.

@Service("customUserDetailsService")
@Transactional
public class CustomUserDetailsService implements UserDetailsService
{
private static final Log logger = LogFactory.getLog(CustomUserDetailsService.class);

@Autowired
private UserAccountDao userAccountDao;

@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
{
    System.out.println("CustomUserDetailsService: username : " + username);
    UserAccountEntity userAccountEntity = userAccountDao.getByUsername(username);
    System.out.println("CustomUserDetailsService: userAccountEntity : " + userAccountEntity);
    if (userAccountEntity == null)
    {
        System.out.println("CustomUserDetailsService: userAccountEntity not found");
        throw new UsernameNotFoundException("Username not found");
    }

    System.out.println("CustomUserDetailsService: START: springframework.user");
    // this "User" object is: org.springframework.security.core.userdetails.User
    User user = new User(userAccountEntity.getUsername(), userAccountEntity.getPassword(), true, true, true, true,
        getGrantedAuthorities(userAccountEntity));

    System.out.println("CustomUserDetailsService: FINISH: springframework.user = " + user);
    return user;
}

private List<GrantedAuthority> getGrantedAuthorities(UserAccountEntity userAccountEntity)
{
    System.out.println("getGrantedAuthorities: START");
    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();

    for (UserRoleEntity userRoleEntity : userAccountEntity.getUserRoleList())
    {
        System.out.println("getGrantedAuthorities: UserRoleEntity : " + userRoleEntity);
        authorities.add(new SimpleGrantedAuthority("ROLE_" + userRoleEntity.getUserRoleName()));
    }
    System.out.print("authorities :" + authorities);
    return authorities;
}

}

下面是另一块安全code的,我不知道这对我的作品或没有。因为在这种情况下,我期待在pre-认证策略,我不知道其中是否真正适用于这种情况。我也看到,我可以实现一个RequestHeaderFilter,但我也不懂这是如何结合使用。

Here is another piece of security code that I am not sure if this works for me or not. Since in this case, I am really looking at Pre-Authentication strategies, and I am not sure if any of them really apply in this case. I also see that I can implement a RequestHeaderFilter, but I am also not sure how this fits in.

public class CustomAuthenticationProvider implements AuthenticationProvider
{
@Autowired
private CustomUserDetailsService userService;

public Authentication authenticate(Authentication authentication) throws AuthenticationException
{
    String username = authentication.getName();
    String password = (String) authentication.getCredentials();

    UserDetails user = userService.loadUserByUsername(username);

    if (user == null || !user.getUsername().equalsIgnoreCase(username))
    {
        throw new BadCredentialsException("Username not found.");
    }

    if (!password.equals(user.getPassword()))
    {
        throw new BadCredentialsException("Wrong password.");
    }

    Collection<? extends GrantedAuthority> authorities = user.getAuthorities();

    return new UsernamePasswordAuthenticationToken(user, password, authorities);
}

public boolean supports(Class<?> arg0)
{
    return true;
}

}

所以,我拉着在一些code和试图使这一切是如何工作如何其他人的工作方案的许多细微变化基于感。
同样,我这是从第三方API来,放在一个cookie的标记。所以,我一直在寻找记得,我这情景绝对是有道理的,我...除了当令牌无效,过期或不存在,那么我重新定向到第三方登录页面。我以为我看到被赋予了URL定制登录表单的例子,因此,如果认证是无效的(令牌不存在或无效),那么我们没有被授权,并发送回自定义登录网址这会工作对我来说。

So, I am pulling in some code and trying to make sense of how this all works based on the many slight variations of how other people have working solutions. Again, I have a token which is coming from a third-party API and put in a cookie. So, I was looking at remember-me scenarios which absolutely makes sense for me ... except that when the token is not valid, expires, or does not exist, then I am re-directed to that third-party login page. I thought I saw an example of a custom login form that was given a URL, so if authentication was not valid (token either does not exist or is not valid) then we are not authorized and sent back to that custom login url which would work for me.

...然后使用该用户名来加载的UserDetails和角色,并把在SecurityContext的?

Based on what I have already added, I should be able to get a username from the token after I pass it to OpenAM ... but do I need a requestheader filter of some sort to get it first ... then use that username to load the userdetails and roles and put that in the SecurityContext?

我只是一个noobie所有这一切的Spring Security的管道,所以用这个特殊的设置会对他帮助很大的帮助。而且顺便说一句,我不介意使用XML春季安全配置。如果我需要添加我的web.xml文件中,我能做到这一点还可以,但请presume我做了正确的设置我的web.xml。谢谢!

I'm just a noobie to all this Spring Security piping, so any help with this particular setup would he greatly helpful. And BTW, I don't mind using XML for spring security configuration. If I need to add my web.xml file, I can do that also, but please presume I did setup my web.xml correctly. Thanks!

更新:
我有一个单元测试,如下:

UPDATED: I have a Unit test that looks like:

@Test
public void testMockGetById() throws Exception
{
    MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get(BASE_URL + "/trialId/149");
    this.mockMvc.perform(requestBuilder).andDo(print()).andExpect(status().isOk());
}

根据该建议采用以下在SiteMinder例子。现在我正在寻找所谓的openam_token而不是SM_USER我已经测试了这个没有令牌的请求头,而我得到的500错误是没有道理。

Based on the SiteMinder example that is suggested below. I am now looking for a request header called "openam_token" and not "SM_USER" I have already tested this without a token, and I get the 500 error that there is no token.

所以,现在我需要改变我的单元测试在请求头添加的令牌。此标记将返回谁有权访问这个URL正确的用户。第二测试是有来自一个不同的用户,一个不具有访问该网址的令牌。如果我的测试条件下工作,我认为这是一个双赢。

So, now I need to alter my unit test to add a token in the request header. This token will return the correct user who has access to this URL. The second test is to have a token that comes from a different user, one that does not have access to this URL. If my test conditions work, I'd consider this a win.

推荐答案

SiteMinder的认证以类似的方式在负载平衡器(Apache)的设置请求头的工作原理。我建议在看关于SiteMinder的是如何建立与春季安全的例子。请参见并春天DOC rel=\"nofollow\">。

Siteminder authentication works in a similar fashion setting a request header at the load balancer (Apache). I would recommend looking at examples on how siteminder is set up with spring security. See this and spring doc here.

别以为你需要的 CustomAuthenticationProvider ,因为认证被前处理的请求到达您的REST API。

Don't think you need the CustomAuthenticationProvider since authentication is being handled before requests reach your rest API.

这篇关于Spring Security的4与第三方认证令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆