spring-oauth2原理及使用(REST)

阅读更多

spring-oauth2 (bearer)是基于spring-security的验证机制,对于第三方访问受限资源时通过token机制来验证

验证steps:


spring-oauth2原理及使用(REST)_第1张图片
 
通过时序图来看一下,验证方式:

 

发送username, password, client_id, client_secret, grant_typeserver

 

server返回包括access_token, token_type, refresh_token, expires_in


spring-oauth2原理及使用(REST)_第2张图片
 
其中,expires_in有效期,如果超期了,refresh_token起作用,如下:

使用refresh_token重新发起验证请求


spring-oauth2原理及使用(REST)_第3张图片
 
来看一下,如何通过spring配置,完成上面的验证机制:

 


 
    
        
        
        
        
        
    
 
    
        
        
        
        
    
 
    
    
 
    
        
        
    
 
    
    
 
    
        
    
 
    
        
    
 
    
        
    
 
    
        
        
    
 
    
        
    
 
    
    
 
    
        
        
        
        
        
    
 
    
 
    
 
    
        
        
        
        
    
 
    
 
    
 
    
 
    
    

 通过发起/oauth/token 请求, filter拦截处理,具体代码:

 

 

@Service
public class AAAGuestServiceImpl implements ClientDetailsService {
 
    private String id;
    private String secretKey;
 
    @Override
    public ClientDetails loadClientByClientId(String clientId)
            throws OAuth2Exception {
 
        if (clientId.equals(id))
        {
            List authorizedGrantTypes = new ArrayList();
            authorizedGrantTypes.add("password");
            authorizedGrantTypes.add("refresh_token");
            authorizedGrantTypes.add("client_credentials");
 
            BaseClientDetails clientDetails = new BaseClientDetails();
            clientDetails.setClientId(id);
            clientDetails.setClientSecret(secretKey);
            clientDetails.setAuthorizedGrantTypes(authorizedGrantTypes);
 
            return clientDetails;
        }
        else {
            throw new NoSuchClientException("No client recognized with id: "
                    + clientId);
        }
    }
 
    public String getId() {
        return id;
    }
 
    public void setId(String id) {
        this.id = id;
    }
 
    public String getSecretKey() {
        return secretKey;
    }
 
    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }
 
}

 现在基于username和passwd来验证(grant_type=password), 在的拦截userAuthenticationManager中:

 

 

public class AAAUserAuthenticationProvider
 
implements AuthenticationProvider {
 
    @Autowired
    AAAProxy aaaProxy;
 
    @Override
    public Authentication authenticate(Authentication authentication)
            throws AuthenticationException {
 
        boolean result = aaaProxy.isValidUser(authentication.getPrincipal()
                .toString(), authentication.getCredentials().toString());
 
        if (result) {
            List grantedAuthorities =
 
new ArrayList();
            AAAUserAuthenticationToken auth =
 
new AAAUserAuthenticationToken(authentication.getPrincipal(),
            authentication.getCredentials(), grantedAuthorities);
 
            return auth;
        } else {
            throw new BadCredentialsException("Bad User Credentials.");
        }
    }
 
    public boolean supports(Class arg0) {
        return true;
    }
}

 这里的aaproxy是真正来验证user的(代理机制)不细化了,如果用户是有效,做三件事:

 

1. 在框架的security上下文中更新对象

2. TokenService将会生成一个新的token

3. TokenStore将会保存这个token

然后token就发给request的client了

最后这里是token和resource的代码:

 

public class AAAUserAuthenticationToken 
 
extends AbstractAuthenticationToken {
 
    private static final long serialVersionUID = -1092219614309982278L;
    private final Object principal;
    private Object credentials;
 
    public AAAUserAuthenticationToken(Object principal, Object credentials,
            Collection authorities) {
        super(authorities);
        this.principal = principal;
        this.credentials = credentials;
        super.setAuthenticated(true);
    }
 
    public Object getCredentials() {
        return this.credentials;
    }
 
    public Object getPrincipal() {
        return this.principal;
    }
}

 

@Path("/userresource")
public class UserResource {
 
    @GET
    @Path("/userprofile")
    public String getUserProfile(){
        return "Welcome in protected Area. User enabled.";
    }
}

 

 

测试:

使用了Fidder, 可以用curl,wget(what ever you want)

请求:

/OAuthAAA/oauth/token ?username=myuser&password=mypassword
&client_id=mysupplycompany&client_secret=mycompanykey&grant_type=password


spring-oauth2原理及使用(REST)_第4张图片
 
 

资源请求:

/OAuthAAA/protected/userresource/userprofile
Authorization: Bearer 5cf0732b-6bbb-40c7-8fab-dcfefcc2fcfe

spring-oauth2原理及使用(REST)_第5张图片
 

 

 

补充:AAProxy的代码:

 

package it.iol.oauthaaa.security;
 
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.util.List;
 
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
 
public class AAAProxy {
 
    private Proxy proxy;
    private RestTemplate template;
 
    public AAAProxy() {
        proxy = new Proxy(Type.HTTP, new InetSocketAddress(
                "proxy.abc.net", 3001));
 
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
 
        requestFactory.setProxy(proxy);
 
        template = new RestTemplate(requestFactory);
    }
 
    public boolean isValidUser(String user, String password) {
 
        MultiValueMap map = new LinkedMultiValueMap();
        map.add("user", user);
        map.add("password", password);
 
        HttpEntity response = template.postForEntity(
                "https://authentication.local/auth", map,
                String.class);
 
        HttpHeaders headers = response.getHeaders();
 
        List cookies = headers.get("Set-Cookie");
 
        for (String cookie : cookies) {
            if (cookie.indexOf("Auth")!=-1)
                return true;
        }
 
        return false;
    }
 
}

 

 

当grant_type="client_credentials"时的验证:


spring-oauth2原理及使用(REST)_第6张图片
 

 

 相关资源:

https://raymondhlee.wordpress.com/2014/12/21/implementing-oauth2-with-spring-security/

https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/BearerTokenExtractor.java

https://github.com/spring-projects/spring-security-oauth/tree/master/spring-security-oauth2

https://developer.linkedin.com/docs/oauth2

http://api-doc.assembla.com/content/authentication.html

 

  • spring-oauth2原理及使用(REST)_第7张图片
  • 大小: 74.1 KB
  • spring-oauth2原理及使用(REST)_第8张图片
  • 大小: 35.7 KB
  • spring-oauth2原理及使用(REST)_第9张图片
  • 大小: 42.8 KB
  • spring-oauth2原理及使用(REST)_第10张图片
  • 大小: 20.3 KB
  • spring-oauth2原理及使用(REST)_第11张图片
  • 大小: 27.5 KB
  • spring-oauth2原理及使用(REST)_第12张图片
  • 大小: 76.9 KB
  • 查看图片附件

你可能感兴趣的:(spring-oauth2原理及使用(REST))