nayutaya-wsse 0.0.0 → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/wsse/authenticator.rb +28 -0
- data/lib/wsse/core.rb +2 -3
- data/lib/wsse/username_token.rb +90 -0
- data/lib/wsse/version.rb +1 -1
- data/nayutaya-wsse.gemspec +8 -11
- data/test/wsse_authenticator_test.rb +32 -0
- data/test/wsse_username_token_test.rb +179 -0
- metadata +8 -11
- data/lib/wsse/http_header.rb +0 -1
- data/lib/wsse/username_token_builder.rb +0 -42
- data/lib/wsse/username_token_parser.rb +0 -24
- data/test/wsse_http_header_test.rb +0 -12
- data/test/wsse_username_token_builder_test.rb +0 -115
- data/test/wsse_username_token_parser_test.rb +0 -66
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require "wsse/username_token"
|
4
|
+
|
5
|
+
module Wsse
|
6
|
+
module Authenticator
|
7
|
+
def self.authenticate(token, username, password)
|
8
|
+
return :wrong_username unless judge_username(token, username)
|
9
|
+
return :wrong_password unless judge_password(token, password)
|
10
|
+
return :success
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.judge_username(token, username)
|
14
|
+
return (token.username == username)
|
15
|
+
end
|
16
|
+
private_class_method :judge_username
|
17
|
+
|
18
|
+
def self.judge_password(token, password)
|
19
|
+
digest = UsernameToken.create_password_digest(password, token.nonce, token.created)
|
20
|
+
return (token.digest == digest)
|
21
|
+
end
|
22
|
+
private_class_method :judge_password
|
23
|
+
|
24
|
+
def self.authenticate?(token, username, password)
|
25
|
+
return (self.authenticate(token, username, password) == :success)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/wsse/core.rb
CHANGED
@@ -0,0 +1,90 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require "time"
|
4
|
+
require "digest/sha1"
|
5
|
+
|
6
|
+
module Wsse
|
7
|
+
class UsernameToken
|
8
|
+
def initialize(username, digest, nonce, created)
|
9
|
+
@username = username
|
10
|
+
@digest = digest # binary
|
11
|
+
@nonce = nonce # binary
|
12
|
+
@created = created # Time object
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :username, :digest, :nonce, :created
|
16
|
+
|
17
|
+
def self.create_random_binary(size)
|
18
|
+
return size.times.map { rand(256) }.pack("C*")
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.create_password_digest(password, nonce, created)
|
22
|
+
return Digest::SHA1.digest(nonce + created.utc.iso8601 + password)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.build(username, password, nonce = nil, created = nil)
|
26
|
+
nonce ||= self.create_random_binary(20)
|
27
|
+
created ||= Time.now.utc
|
28
|
+
digest = self.create_password_digest(password, nonce, created)
|
29
|
+
return self.new(username, digest, nonce, created)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.parse_token(token)
|
33
|
+
if /\AUsernameToken (.+?=".+?"(?:, .+?=".+?")*)\z/ =~ token.to_s
|
34
|
+
return $1.scan(/(?:\A|, )(.+?)="(.+?)"/).inject({}) { |memo, (key, value)|
|
35
|
+
memo[key] = value
|
36
|
+
memo
|
37
|
+
}
|
38
|
+
else
|
39
|
+
return nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.parse_time(value)
|
44
|
+
if /\A(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)Z\z/ =~ value.to_s
|
45
|
+
return Time.utc(*($~.captures.map { |s| s.to_i }))
|
46
|
+
else
|
47
|
+
return nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.format_token_values(username, digest, nonce, created)
|
52
|
+
return format(
|
53
|
+
%|UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"|,
|
54
|
+
username, digest, nonce, created)
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.parse(token)
|
58
|
+
parsed_token = self.parse_token(token)
|
59
|
+
return nil unless parsed_token
|
60
|
+
|
61
|
+
username = parsed_token["Username"]
|
62
|
+
digest = parsed_token["PasswordDigest"]
|
63
|
+
nonce = parsed_token["Nonce"]
|
64
|
+
created = parsed_token["Created"]
|
65
|
+
return nil if [username, digest, nonce, created].include?(nil)
|
66
|
+
|
67
|
+
return self.new(
|
68
|
+
username,
|
69
|
+
digest.unpack("m")[0],
|
70
|
+
nonce.unpack("m")[0],
|
71
|
+
self.parse_time(created))
|
72
|
+
end
|
73
|
+
|
74
|
+
def base64encoded_digest
|
75
|
+
return [@digest].pack("m").chomp
|
76
|
+
end
|
77
|
+
|
78
|
+
def base64encoded_nonce
|
79
|
+
return [@nonce].pack("m").chomp
|
80
|
+
end
|
81
|
+
|
82
|
+
def format
|
83
|
+
return self.class.format_token_values(
|
84
|
+
self.username,
|
85
|
+
self.base64encoded_digest,
|
86
|
+
self.base64encoded_nonce,
|
87
|
+
self.created.utc.iso8601)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/lib/wsse/version.rb
CHANGED
data/nayutaya-wsse.gemspec
CHANGED
@@ -5,8 +5,8 @@ Gem::Specification.new do |s|
|
|
5
5
|
s.required_ruby_version = Gem::Requirement.new(">= 1.8.6")
|
6
6
|
|
7
7
|
s.name = "nayutaya-wsse"
|
8
|
-
s.version = "0.0.
|
9
|
-
s.date = "2009-10-
|
8
|
+
s.version = "0.0.1"
|
9
|
+
s.date = "2009-10-29"
|
10
10
|
|
11
11
|
s.authors = ["Yuya Kato"]
|
12
12
|
s.email = "yuyakato@gmail.com"
|
@@ -23,23 +23,20 @@ Gem::Specification.new do |s|
|
|
23
23
|
"README",
|
24
24
|
"Rakefile",
|
25
25
|
"lib/wsse.rb",
|
26
|
+
"lib/wsse/authenticator.rb",
|
26
27
|
"lib/wsse/core.rb",
|
27
|
-
"lib/wsse/
|
28
|
-
"lib/wsse/username_token_builder.rb",
|
29
|
-
"lib/wsse/username_token_parser.rb",
|
28
|
+
"lib/wsse/username_token.rb",
|
30
29
|
"lib/wsse/version.rb",
|
31
30
|
"nayutaya-wsse.gemspec",
|
32
31
|
"nayutaya-wsse.gemspec.erb",
|
33
32
|
"test/test_helper.rb",
|
34
|
-
"test/
|
35
|
-
"test/
|
36
|
-
"test/wsse_username_token_parser_test.rb",
|
33
|
+
"test/wsse_authenticator_test.rb",
|
34
|
+
"test/wsse_username_token_test.rb",
|
37
35
|
]
|
38
36
|
s.test_files = [
|
39
37
|
"test/test_helper.rb",
|
40
|
-
"test/
|
41
|
-
"test/
|
42
|
-
"test/wsse_username_token_parser_test.rb",
|
38
|
+
"test/wsse_authenticator_test.rb",
|
39
|
+
"test/wsse_username_token_test.rb",
|
43
40
|
]
|
44
41
|
s.extra_rdoc_files = []
|
45
42
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + "/test_helper"
|
4
|
+
require "wsse/authenticator"
|
5
|
+
|
6
|
+
class WsseAuthenticatorTest < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
@mod = Wsse::Authenticator
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_authenticate__success
|
12
|
+
token = Wsse::UsernameToken.build("username", "password")
|
13
|
+
assert_equal(:success, @mod.authenticate(token, "username", "password"))
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_authenticate__wrong_username
|
17
|
+
token = Wsse::UsernameToken.build("username", "password")
|
18
|
+
assert_equal(:wrong_username, @mod.authenticate(token, "foo", "password"))
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_authenticate__wrong_password
|
22
|
+
token = Wsse::UsernameToken.build("username", "password")
|
23
|
+
assert_equal(:wrong_password, @mod.authenticate(token, "username", "baz"))
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_authenticate_p
|
27
|
+
token = Wsse::UsernameToken.build("username", "password")
|
28
|
+
assert_equal(true, @mod.authenticate?(token, "username", "password"))
|
29
|
+
assert_equal(false, @mod.authenticate?(token, "foo", "password"))
|
30
|
+
assert_equal(false, @mod.authenticate?(token, "username", "baz"))
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + "/test_helper"
|
4
|
+
require "wsse/username_token"
|
5
|
+
|
6
|
+
class WsseUsernameTokenTest < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
@klass = Wsse::UsernameToken
|
9
|
+
@musha = Kagemusha.new(@klass)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_initialize_and_accessor
|
13
|
+
created = Time.utc(2000, 1, 1)
|
14
|
+
token = Wsse::UsernameToken.new("username", "digest", "nonce", created)
|
15
|
+
assert_equal("username", token.username)
|
16
|
+
assert_equal("digest", token.digest)
|
17
|
+
assert_equal("nonce", token.nonce)
|
18
|
+
assert_equal(created, token.created)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_create_random_binary
|
22
|
+
srand(0)
|
23
|
+
assert_equal(20, @klass.create_random_binary(20).size)
|
24
|
+
assert_equal(30, @klass.create_random_binary(30).size)
|
25
|
+
assert_equal(10, 10.times.map { @klass.create_random_binary(20) }.uniq.size)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_create_password_digest
|
29
|
+
assert_equal(
|
30
|
+
Digest::SHA1.digest("nonce2000-01-01T00:00:00Zpassword"),
|
31
|
+
@klass.create_password_digest("password", "nonce", Time.utc(2000, 1, 1)))
|
32
|
+
assert_equal(
|
33
|
+
Digest::SHA1.digest("bar1999-12-31T23:59:59Zfoo"),
|
34
|
+
@klass.create_password_digest("foo", "bar", Time.utc(1999, 12, 31, 23, 59, 59)))
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_build
|
38
|
+
created = Time.utc(2000, 1, 1)
|
39
|
+
digest = @klass.create_password_digest("password", "nonce", created)
|
40
|
+
token = @klass.build("username", "password", "nonce", created)
|
41
|
+
assert_kind_of(@klass, token)
|
42
|
+
assert_equal("username", token.username)
|
43
|
+
assert_equal(digest, token.digest)
|
44
|
+
assert_equal("nonce", token.nonce)
|
45
|
+
assert_equal(created, token.created)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_build__default_created
|
49
|
+
created = Time.utc(1999, 12, 31, 23, 59, 59)
|
50
|
+
|
51
|
+
token =
|
52
|
+
Kagemusha::DateTime.at(created) {
|
53
|
+
@klass.build("username", "password", "nonce")
|
54
|
+
}
|
55
|
+
|
56
|
+
assert_equal(created, token.created)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_build__default_nonce
|
60
|
+
nonce = "foo"
|
61
|
+
|
62
|
+
@musha.defs(:create_random_binary) { |size|
|
63
|
+
raise unless size == 20
|
64
|
+
nonce
|
65
|
+
}
|
66
|
+
token =
|
67
|
+
@musha.swap {
|
68
|
+
@klass.build("username", "password")
|
69
|
+
}
|
70
|
+
|
71
|
+
assert_equal(nonce, token.nonce)
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_parse_token__1
|
75
|
+
# http://www.teria.com/~koseki/tools/wssegen/
|
76
|
+
# UserName: test, Password: test, Nonce: auto, Created: auto
|
77
|
+
token = %|UsernameToken Username="test", PasswordDigest="XYuMkeTAdwEwKhyU/4uw/pbvqrc=", Nonce="Mzg5ODU5MDExYTljODQ5Yg==", Created="2009-10-08T02:31:57Z"|
|
78
|
+
expected = {
|
79
|
+
"Username" => "test",
|
80
|
+
"PasswordDigest" => "XYuMkeTAdwEwKhyU/4uw/pbvqrc=",
|
81
|
+
"Nonce" => "Mzg5ODU5MDExYTljODQ5Yg==",
|
82
|
+
"Created" => "2009-10-08T02:31:57Z",
|
83
|
+
}
|
84
|
+
assert_equal(expected, @klass.parse_token(token))
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_parse_token__2
|
88
|
+
# http://d.hatena.ne.jp/keyword/%A4%CF%A4%C6%A4%CA%A5%D5%A5%A9%A5%C8%A5%E9%A5%A4%A5%D5AtomAPI
|
89
|
+
token = %|UsernameToken Username="hatena", PasswordDigest="ZCNaK2jrXr4+zsCaYK/YLUxImZU=", Nonce="Uh95NQlviNpJQR1MmML+zq6pFxE=", Created="2005-01-18T03:20:15Z"|
|
90
|
+
expected = {
|
91
|
+
"Username" => "hatena",
|
92
|
+
"PasswordDigest" => "ZCNaK2jrXr4+zsCaYK/YLUxImZU=",
|
93
|
+
"Nonce" => "Uh95NQlviNpJQR1MmML+zq6pFxE=",
|
94
|
+
"Created" => "2005-01-18T03:20:15Z",
|
95
|
+
}
|
96
|
+
assert_equal(expected, @klass.parse_token(token))
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_parse_token__3
|
100
|
+
# http://www.witha.jp/blog/archives/2004/06/_atom_api.html
|
101
|
+
token = %|UsernameToken Username="Melody", PasswordDigest="VfJavTaTy3BhKkeY/WVu9L6cdVA=", Created="2004-01-20T01:09:39Z", Nonce="7c19aeed85b93d35ba42e357f10ca19bf314d622"|
|
102
|
+
expected = {
|
103
|
+
"Username" => "Melody",
|
104
|
+
"PasswordDigest" => "VfJavTaTy3BhKkeY/WVu9L6cdVA=",
|
105
|
+
"Nonce" => "7c19aeed85b93d35ba42e357f10ca19bf314d622",
|
106
|
+
"Created" => "2004-01-20T01:09:39Z",
|
107
|
+
}
|
108
|
+
assert_equal(expected, @klass.parse_token(token))
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_parse_token__empty
|
112
|
+
assert_equal(nil, @klass.parse_token(nil))
|
113
|
+
assert_equal(nil, @klass.parse_token(""))
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_parse_time
|
117
|
+
assert_equal(Time.utc(2000, 1, 1, 0, 0, 0), @klass.parse_time("2000-01-01T00:00:00Z"))
|
118
|
+
assert_equal(Time.utc(1999, 12, 31, 23, 59, 59), @klass.parse_time("1999-12-31T23:59:59Z"))
|
119
|
+
assert_equal(Time.utc(2001, 2, 3, 4, 5, 6), @klass.parse_time("2001-02-03T04:05:06Z"))
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_parse_time__empty
|
123
|
+
assert_equal(nil, @klass.parse_time(nil))
|
124
|
+
assert_equal(nil, @klass.parse_time(""))
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_parse__1
|
128
|
+
token = @klass.parse(%|UsernameToken Username="username", PasswordDigest="ZGlnZXN0", Nonce="bm9uY2U=", Created="2000-01-01T00:00:00Z"|)
|
129
|
+
assert_kind_of(@klass, token)
|
130
|
+
assert_equal("username", token.username)
|
131
|
+
assert_equal("digest", token.digest)
|
132
|
+
assert_equal("nonce", token.nonce)
|
133
|
+
assert_equal(Time.utc(2000, 1, 1), token.created)
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_parse__2
|
137
|
+
token = @klass.parse(%|UsernameToken Username="foo", PasswordDigest="YmFy", Nonce="YmF6", Created="1999-12-31T23:59:59Z"|)
|
138
|
+
assert_kind_of(@klass, token)
|
139
|
+
assert_equal("foo", token.username)
|
140
|
+
assert_equal("bar", token.digest)
|
141
|
+
assert_equal("baz", token.nonce)
|
142
|
+
assert_equal(Time.utc(1999, 12, 31, 23, 59, 59), token.created)
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_parse__3
|
146
|
+
assert_equal(nil, @klass.parse(%|UsernameToken PasswordDigest="ZGlnZXN0", Nonce="bm9uY2U=", Created="2000-01-01T00:00:00Z"|))
|
147
|
+
assert_equal(nil, @klass.parse(%|UsernameToken Username="username", Nonce="bm9uY2U=", Created="2000-01-01T00:00:00Z"|))
|
148
|
+
assert_equal(nil, @klass.parse(%|UsernameToken Username="username", PasswordDigest="ZGlnZXN0", Created="2000-01-01T00:00:00Z"|))
|
149
|
+
assert_equal(nil, @klass.parse(%|UsernameToken Username="username", PasswordDigest="ZGlnZXN0", Nonce="bm9uY2U="|))
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_parse__empty
|
153
|
+
assert_equal(nil, @klass.parse(""))
|
154
|
+
assert_equal(nil, @klass.parse(nil))
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_format_token_values
|
158
|
+
assert_equal(
|
159
|
+
%|UsernameToken Username="a", PasswordDigest="b", Nonce="c", Created="d"|,
|
160
|
+
@klass.format_token_values("a", "b", "c", "d"))
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_base64encoded_digest
|
164
|
+
token = @klass.new("username", "digest", "nonce", Time.utc(2000, 1, 1))
|
165
|
+
assert_equal("ZGlnZXN0", token.base64encoded_digest)
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_base64encoded_nonce
|
169
|
+
token = @klass.new("username", "digest", "nonce", Time.utc(2000, 1, 1))
|
170
|
+
assert_equal("bm9uY2U=", token.base64encoded_nonce)
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_format
|
174
|
+
token = @klass.build("username", "password", "nonce", Time.utc(2000, 1, 1))
|
175
|
+
assert_equal(
|
176
|
+
%|UsernameToken Username="username", PasswordDigest="DzunnEf/2CKuhInsnmEHonW5qQs=", Nonce="bm9uY2U=", Created="2000-01-01T00:00:00Z"|,
|
177
|
+
token.format)
|
178
|
+
end
|
179
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nayutaya-wsse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yuya Kato
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-10-
|
12
|
+
date: 2009-10-29 00:00:00 +09:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -25,17 +25,15 @@ files:
|
|
25
25
|
- README
|
26
26
|
- Rakefile
|
27
27
|
- lib/wsse.rb
|
28
|
+
- lib/wsse/authenticator.rb
|
28
29
|
- lib/wsse/core.rb
|
29
|
-
- lib/wsse/
|
30
|
-
- lib/wsse/username_token_builder.rb
|
31
|
-
- lib/wsse/username_token_parser.rb
|
30
|
+
- lib/wsse/username_token.rb
|
32
31
|
- lib/wsse/version.rb
|
33
32
|
- nayutaya-wsse.gemspec
|
34
33
|
- nayutaya-wsse.gemspec.erb
|
35
34
|
- test/test_helper.rb
|
36
|
-
- test/
|
37
|
-
- test/
|
38
|
-
- test/wsse_username_token_parser_test.rb
|
35
|
+
- test/wsse_authenticator_test.rb
|
36
|
+
- test/wsse_username_token_test.rb
|
39
37
|
has_rdoc: true
|
40
38
|
homepage: http://github.com/nayutaya/wsse/
|
41
39
|
licenses: []
|
@@ -66,6 +64,5 @@ specification_version: 2
|
|
66
64
|
summary: X-WSSE header builder and parser
|
67
65
|
test_files:
|
68
66
|
- test/test_helper.rb
|
69
|
-
- test/
|
70
|
-
- test/
|
71
|
-
- test/wsse_username_token_parser_test.rb
|
67
|
+
- test/wsse_authenticator_test.rb
|
68
|
+
- test/wsse_username_token_test.rb
|
data/lib/wsse/http_header.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
require "time"
|
4
|
-
require "digest/sha1"
|
5
|
-
|
6
|
-
module Wsse
|
7
|
-
module UsernameTokenBuilder
|
8
|
-
def self.create_created_time(time = Time.now)
|
9
|
-
return time.utc.iso8601
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.create_nonce
|
13
|
-
return 20.times.map { rand(256) }.pack("C*")
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.create_token_params(username, password, nonce = nil, created = nil)
|
17
|
-
nonce ||= self.create_nonce
|
18
|
-
created ||= self.create_created_time
|
19
|
-
digest = Digest::SHA1.digest(nonce + created + password)
|
20
|
-
return {
|
21
|
-
"Username" => username,
|
22
|
-
"PasswordDigest" => [digest].pack("m").chomp,
|
23
|
-
"Nonce" => [nonce].pack("m").chomp,
|
24
|
-
"Created" => created,
|
25
|
-
}
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.format_token(params)
|
29
|
-
return format(
|
30
|
-
%|UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"|,
|
31
|
-
(params["Username"] || raise(ArgumentError)),
|
32
|
-
(params["PasswordDigest"] || raise(ArgumentError)),
|
33
|
-
(params["Nonce"] || raise(ArgumentError)),
|
34
|
-
(params["Created"] || raise(ArgumentError)))
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.create_token(username, password, nonce = nil, created = nil)
|
38
|
-
params = self.create_token_params(username, password, nonce, created)
|
39
|
-
return self.format_token(params)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
module Wsse
|
4
|
-
module UsernameTokenParser
|
5
|
-
def self.parse(value)
|
6
|
-
if /\AUsernameToken (.+?=".+?"(?:, .+?=".+?")*)\z/ =~ value.to_s
|
7
|
-
return $1.scan(/(?:\A|, )(.+?)="(.+?)"/).inject({}) { |memo, (key, value)|
|
8
|
-
memo[key] = value
|
9
|
-
memo
|
10
|
-
}
|
11
|
-
else
|
12
|
-
return nil
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.parse_time(value)
|
17
|
-
if /\A(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)Z\z/ =~ value.to_s
|
18
|
-
return Time.utc(*($~.captures.map { |s| s.to_i }))
|
19
|
-
else
|
20
|
-
return nil
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,115 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
require File.dirname(__FILE__) + "/test_helper"
|
4
|
-
require "wsse/username_token_builder"
|
5
|
-
|
6
|
-
class WsseUsernameTokenBuilderTest < Test::Unit::TestCase
|
7
|
-
def setup
|
8
|
-
@mod = Wsse::UsernameTokenBuilder
|
9
|
-
@musha = Kagemusha.new(@mod)
|
10
|
-
end
|
11
|
-
|
12
|
-
def test_create_created_time
|
13
|
-
assert_equal("2000-01-01T00:00:00Z", @mod.create_created_time(Time.utc(2000, 1, 1, 0, 0, 0)))
|
14
|
-
assert_equal("2001-12-31T23:59:59Z", @mod.create_created_time(Time.utc(2001, 12, 31, 23, 59, 59)))
|
15
|
-
Kagemusha::DateTime.at(Time.utc(2009, 1, 2, 3, 4, 5)) {
|
16
|
-
assert_equal("2009-01-02T03:04:05Z", @mod.create_created_time())
|
17
|
-
}
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_create_nonce
|
21
|
-
srand(0)
|
22
|
-
assert_equal(20, @mod.create_nonce.size)
|
23
|
-
assert_equal(10, 10.times.map { @mod.create_nonce }.uniq.size)
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_create_token_params
|
27
|
-
username = "username"
|
28
|
-
password = "password"
|
29
|
-
nonce = "nonce"
|
30
|
-
created = "2000-01-01T00:00:00Z"
|
31
|
-
expected = {
|
32
|
-
"Username" => username,
|
33
|
-
"PasswordDigest" => [Digest::SHA1.digest("#{nonce}#{created}#{password}")].pack("m").chomp,
|
34
|
-
"Nonce" => [nonce].pack("m").chomp,
|
35
|
-
"Created" => created,
|
36
|
-
}
|
37
|
-
assert_equal(expected, @mod.create_token_params(username, password, nonce, created))
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_create_token_params__default_created
|
41
|
-
username = "username1"
|
42
|
-
password = "password1"
|
43
|
-
nonce = "nonce"
|
44
|
-
created = "2001-02-03T04:05:06Z"
|
45
|
-
expected = {
|
46
|
-
"Username" => username,
|
47
|
-
"PasswordDigest" => [Digest::SHA1.digest("#{nonce}#{created}#{password}")].pack("m").chomp,
|
48
|
-
"Nonce" => [nonce].pack("m").chomp,
|
49
|
-
"Created" => created,
|
50
|
-
}
|
51
|
-
@musha.defs(:create_created_time) { created }
|
52
|
-
@musha.swap {
|
53
|
-
assert_equal(expected, @mod.create_token_params(username, password, nonce))
|
54
|
-
}
|
55
|
-
end
|
56
|
-
|
57
|
-
def test_create_token_params__default_nonce
|
58
|
-
username = "username2"
|
59
|
-
password = "password2"
|
60
|
-
nonce = "foobarbaz"
|
61
|
-
created = "2001-02-03T04:05:06Z"
|
62
|
-
expected = {
|
63
|
-
"Username" => username,
|
64
|
-
"PasswordDigest" => [Digest::SHA1.digest("#{nonce}#{created}#{password}")].pack("m").chomp,
|
65
|
-
"Nonce" => [nonce].pack("m").chomp,
|
66
|
-
"Created" => created,
|
67
|
-
}
|
68
|
-
@musha.defs(:create_nonce) { nonce }
|
69
|
-
@musha.defs(:create_created_time) { created }
|
70
|
-
@musha.swap {
|
71
|
-
assert_equal(expected, @mod.create_token_params(username, password))
|
72
|
-
}
|
73
|
-
end
|
74
|
-
|
75
|
-
def test_format_token
|
76
|
-
basic = {
|
77
|
-
"Username" => "username",
|
78
|
-
"PasswordDigest" => "digest",
|
79
|
-
"Nonce" => "nonce",
|
80
|
-
"Created" => "created",
|
81
|
-
}
|
82
|
-
assert_equal(
|
83
|
-
%|UsernameToken Username="username", PasswordDigest="digest", Nonce="nonce", Created="created"|,
|
84
|
-
@mod.format_token(basic))
|
85
|
-
assert_raise(ArgumentError) { @mod.format_token(basic.merge("Username" => nil)) }
|
86
|
-
assert_raise(ArgumentError) { @mod.format_token(basic.merge("PasswordDigest" => nil)) }
|
87
|
-
assert_raise(ArgumentError) { @mod.format_token(basic.merge("Nonce" => nil)) }
|
88
|
-
assert_raise(ArgumentError) { @mod.format_token(basic.merge("Created" => nil)) }
|
89
|
-
end
|
90
|
-
|
91
|
-
def test_create_token
|
92
|
-
assert_equal(
|
93
|
-
%|UsernameToken Username="username", PasswordDigest="DzunnEf/2CKuhInsnmEHonW5qQs=", Nonce="bm9uY2U=", Created="2000-01-01T00:00:00Z"|,
|
94
|
-
@mod.create_token("username", "password", "nonce", "2000-01-01T00:00:00Z"))
|
95
|
-
end
|
96
|
-
|
97
|
-
def test_create_token__default_created
|
98
|
-
@musha.defs(:create_created_time) { "2001-02-03T04:05:06Z" }
|
99
|
-
@musha.swap {
|
100
|
-
assert_equal(
|
101
|
-
%|UsernameToken Username="username1", PasswordDigest="lTTtMZC0IJyrV8aITFjLgdDzXzw=", Nonce="bm9uY2U=", Created="2001-02-03T04:05:06Z"|,
|
102
|
-
@mod.create_token("username1", "password1", "nonce"))
|
103
|
-
}
|
104
|
-
end
|
105
|
-
|
106
|
-
def test_create_token__default_nonce
|
107
|
-
@musha.defs(:create_nonce) { "foobarbaz" }
|
108
|
-
@musha.defs(:create_created_time) { "2001-02-03T04:05:06Z" }
|
109
|
-
@musha.swap {
|
110
|
-
assert_equal(
|
111
|
-
%|UsernameToken Username="username2", PasswordDigest="zmw1lW05c8tDlXsnU1IypUIt8uA=", Nonce="Zm9vYmFyYmF6", Created="2001-02-03T04:05:06Z"|,
|
112
|
-
@mod.create_token("username2", "password2"))
|
113
|
-
}
|
114
|
-
end
|
115
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
require File.dirname(__FILE__) + "/test_helper"
|
4
|
-
require "wsse/username_token_parser"
|
5
|
-
|
6
|
-
class WsseUsernameTokenParserTest < Test::Unit::TestCase
|
7
|
-
def setup
|
8
|
-
@mod = Wsse::UsernameTokenParser
|
9
|
-
end
|
10
|
-
|
11
|
-
def test_parse__1
|
12
|
-
# http://www.teria.com/~koseki/tools/wssegen/
|
13
|
-
# UserName: test, Password: test, Nonce: auto, Created: auto
|
14
|
-
value = %|UsernameToken Username="test", PasswordDigest="XYuMkeTAdwEwKhyU/4uw/pbvqrc=", Nonce="Mzg5ODU5MDExYTljODQ5Yg==", Created="2009-10-08T02:31:57Z"|
|
15
|
-
expected = {
|
16
|
-
"Username" => "test",
|
17
|
-
"PasswordDigest" => "XYuMkeTAdwEwKhyU/4uw/pbvqrc=",
|
18
|
-
"Nonce" => "Mzg5ODU5MDExYTljODQ5Yg==",
|
19
|
-
"Created" => "2009-10-08T02:31:57Z",
|
20
|
-
}
|
21
|
-
assert_equal(expected, @mod.parse(value))
|
22
|
-
end
|
23
|
-
|
24
|
-
def test_parse__2
|
25
|
-
# http://d.hatena.ne.jp/keyword/%A4%CF%A4%C6%A4%CA%A5%D5%A5%A9%A5%C8%A5%E9%A5%A4%A5%D5AtomAPI
|
26
|
-
value = %|UsernameToken Username="hatena", PasswordDigest="ZCNaK2jrXr4+zsCaYK/YLUxImZU=", Nonce="Uh95NQlviNpJQR1MmML+zq6pFxE=", Created="2005-01-18T03:20:15Z"|
|
27
|
-
expected = {
|
28
|
-
"Username" => "hatena",
|
29
|
-
"PasswordDigest" => "ZCNaK2jrXr4+zsCaYK/YLUxImZU=",
|
30
|
-
"Nonce" => "Uh95NQlviNpJQR1MmML+zq6pFxE=",
|
31
|
-
"Created" => "2005-01-18T03:20:15Z",
|
32
|
-
}
|
33
|
-
assert_equal(expected, @mod.parse(value))
|
34
|
-
end
|
35
|
-
|
36
|
-
def test_parse__3
|
37
|
-
# http://www.witha.jp/blog/archives/2004/06/_atom_api.html
|
38
|
-
value = %|UsernameToken Username="Melody", PasswordDigest="VfJavTaTy3BhKkeY/WVu9L6cdVA=", Created="2004-01-20T01:09:39Z", Nonce="7c19aeed85b93d35ba42e357f10ca19bf314d622"|
|
39
|
-
expected = {
|
40
|
-
"Username" => "Melody",
|
41
|
-
"PasswordDigest" => "VfJavTaTy3BhKkeY/WVu9L6cdVA=",
|
42
|
-
"Nonce" => "7c19aeed85b93d35ba42e357f10ca19bf314d622",
|
43
|
-
"Created" => "2004-01-20T01:09:39Z",
|
44
|
-
}
|
45
|
-
assert_equal(expected, @mod.parse(value))
|
46
|
-
end
|
47
|
-
|
48
|
-
def test_parse__nil
|
49
|
-
assert_equal(nil, @mod.parse(nil))
|
50
|
-
end
|
51
|
-
|
52
|
-
def test_parse__empty
|
53
|
-
assert_equal(nil, @mod.parse(""))
|
54
|
-
end
|
55
|
-
|
56
|
-
def test_parse_time
|
57
|
-
assert_equal(Time.utc(2009, 1, 1, 0, 0, 0), @mod.parse_time("2009-01-01T00:00:00Z"))
|
58
|
-
assert_equal(Time.utc(2009, 12, 31, 23, 59, 59), @mod.parse_time("2009-12-31T23:59:59Z"))
|
59
|
-
assert_equal(Time.utc(2001, 2, 3, 4, 5, 6), @mod.parse_time("2001-02-03T04:05:06Z"))
|
60
|
-
end
|
61
|
-
|
62
|
-
def test_parse_time__empty
|
63
|
-
assert_equal(nil, @mod.parse_time(nil))
|
64
|
-
assert_equal(nil, @mod.parse_time(""))
|
65
|
-
end
|
66
|
-
end
|