2012年8月27日 星期一

OAuth for Spring Security 應用實作

參考來源:https://github.com/SpringSource/spring-security-oauth/wiki/tutorial
程式下載:https://github.com/SpringSource/spring-security-oauth 網頁下面有文字說明如何使用 maven將 source code下載回來。

目前 tutorial 有實作 OAuth1, OAuth2 的Server 和 Client, Client 可以下載 Server 的圖片。 而我的目的就是可以建立一個公司內部認證網站(OAuth 是用來作授權用的),使用者在連其它公司自製網站時可以連來這個網站使用 Notes or AD, Oracle ERP 的帳號作登入,當帳號、密碼正確時就可以允許 oauth client 存取 登入使用者的工號、部門、 email等。

修改部份:
首先我選擇的是拿 OAuth2的範列來改,Server  的 source code 代號為 Sparklr2,Client 的代號為 Tonr2。

因為要讓使用者可以用Notes or AD, Oracle ERP 的帳號作登入,所以要先改 OAuth2 Server 的部份,目前 spring security 選擇 authentication的方式有兩種,一種是 AuthenticationProvider ,一種是UserService,我選擇的是AuthenticationProvider ,所以要實作一個 class implements org.springframework.security.authentication.AuthenticationProvider 並實作兩個 method

1.public Authentication authenticate(Authentication authentication)   ==>讓我可以用Notes or AD, Oracle ERP 的帳號、宓碼登入後檢查是否正確。

2. public boolean supports(Class authentication) {
         return authentication.equals(UsernamePasswordAuthenticationToken.class);

     }

等這個 provider實作好之後,就要在 WEB-INF\spring-servlet.xml 內加上設定,這樣就可以完成認證的功能了。





再來就是分享員工資訊的程式了, 可以實作自己的 controller,參考原程式分享 photoID的 service : PhotoController, PhotoServiceImpl,PhotoService
記得WEB-INF\spring-servlet.xml 也要將相關的 tag 加上。

而 Client 的程式也請參考原程式如何存取 photoID
等 server , client 的程式都實作好之後就可以放到 tomcat 上了。 目前實作好之後才發現 Client 要先自己認證完成,才可以去 Server再去作認證一次,才可以存取我的員工資訊,但我想的是 Client 本身不用有認證的程序,直接到  server 作認證後存取資料。上網找了一下資訊,發現好像沒有人分享怎麼設定 OAuth2才可以達到我的要求,所以我又拿了 OAuth1的 source code改了一次。

OAuth1 跟 OAuth2 設定上有一點不一樣,除了WEB-INF\spring-servlet.xml之外,又多了一個檔案 applicationContext.xml,也是 spring 標準設定檔。
這邊也是實作我自己的 AuthenticationProvider ,但是在設定上就不是在 spring-servlet.xml新增 的資訊了,而是要放在 applicationContext.xml 而且 bean 要改為 beans:bean 這樣才可以。 其它 controller or  service的程式才在spring-servlet.xml 註冊。
再來就是 oauth:consumer-details-service id="consumerDetails" 的設定 


這邊就可增加自己   oauth:consumer

實作分享員工資訊的程式也跟 OAuth2實作差不多,設定上 OAuth1 OAuth2會有差異,只要參考原程式存取 photoID怎麼寫和怎麼設定應該就沒什麼大問題了。 


最後我想測試用 asp.net 也可以存取我的 OAuth1實作出來的 server員工資訊,這一次我採用

DotNetOpenAuth  http://www.dotnetopenauth.net/ 

實作自己的 service comsumer

public static readonly ServiceProviderDescription ServiceDescription = new ServiceProviderDescription {
            RequestTokenEndpoint = new MessageReceivingEndpoint("http://ip:port/OAuth1Server/oauth/request_token", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
            UserAuthorizationEndpoint = new MessageReceivingEndpoint("http://ip:port/OAuth1Server /oauth/confirm_access", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
            AccessTokenEndpoint = new MessageReceivingEndpoint("http:// ip:port/OAuth1Server /oauth/access_token", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
};

/// The URI to get the data on the user's home page.
///
        private static readonly MessageReceivingEndpoint cattonEmpInfoEndpoint = new MessageReceivingEndpoint("http:// ip:port/OAuth1Server/service?format=json", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest);


private static InMemoryTokenManager ShortTermUserSessionTokenManager {
get {
var store = HttpContext.Current.Session;
var tokenManager = (InMemoryTokenManager)store["CattonOAuth1SessionTokenManager"];
if (tokenManager == null) {
                    string consumerKey = ConfigurationManager.AppSettings["CattonOAuthConsumerKey"];
                    string consumerSecret = ConfigurationManager.AppSettings["CattonOAuthConsumerSecret"];
if (IsTwitterConsumerConfigured) {
tokenManager = new InMemoryTokenManager(consumerKey, consumerSecret);
                        store["CattonOAuth1SessionTokenManager"] = tokenManager;
} else {
throw new InvalidOperationException("No Catton OAuth consumer key and secret could be found in web.config AppSettings.");
}
}

return tokenManager;
}
}

public static string GetUserInfo(ConsumerBase cattonOAuthCB, string accessToken) {
            IncomingWebResponse response = cattonOAuthCB.PrepareAuthorizedRequestAndSend(cattonEmpInfoEndpoint, accessToken);
          
            return  response.GetResponseReader().ReadToEnd();

}

實作畫面



沒有留言:

張貼留言