1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.ws.soap.security.xwss.callback;
18
19 import java.io.IOException;
20 import javax.security.auth.callback.Callback;
21 import javax.security.auth.callback.UnsupportedCallbackException;
22
23 import com.sun.xml.wss.impl.callback.PasswordValidationCallback;
24 import com.sun.xml.wss.impl.callback.TimestampValidationCallback;
25
26 import org.springframework.beans.factory.InitializingBean;
27 import org.springframework.dao.DataAccessException;
28 import org.springframework.security.core.context.SecurityContextHolder;
29 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
30 import org.springframework.security.core.userdetails.UserCache;
31 import org.springframework.security.core.userdetails.cache.NullUserCache;
32 import org.springframework.security.core.userdetails.UserDetails;
33 import org.springframework.security.core.userdetails.UserDetailsService;
34 import org.springframework.security.core.userdetails.UsernameNotFoundException;
35 import org.springframework.util.Assert;
36 import org.springframework.ws.soap.security.callback.AbstractCallbackHandler;
37 import org.springframework.ws.soap.security.callback.CleanupCallback;
38 import org.springframework.ws.soap.security.support.SpringSecurityUtils;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 public class SpringDigestPasswordValidationCallbackHandler extends AbstractCallbackHandler implements InitializingBean {
57
58 private UserCache userCache = new NullUserCache();
59
60 private UserDetailsService userDetailsService;
61
62
63 public void setUserCache(UserCache userCache) {
64 this.userCache = userCache;
65 }
66
67
68 public void setUserDetailsService(UserDetailsService userDetailsService) {
69 this.userDetailsService = userDetailsService;
70 }
71
72 public void afterPropertiesSet() throws Exception {
73 Assert.notNull(userDetailsService, "userDetailsService is required");
74 }
75
76
77
78
79
80
81
82
83 @Override
84 protected void handleInternal(Callback callback) throws IOException, UnsupportedCallbackException {
85 if (callback instanceof PasswordValidationCallback) {
86 PasswordValidationCallback passwordCallback = (PasswordValidationCallback) callback;
87 if (passwordCallback.getRequest() instanceof PasswordValidationCallback.DigestPasswordRequest) {
88 PasswordValidationCallback.DigestPasswordRequest request =
89 (PasswordValidationCallback.DigestPasswordRequest) passwordCallback.getRequest();
90 String username = request.getUsername();
91 UserDetails user = loadUserDetails(username);
92 if (user != null) {
93 SpringSecurityUtils.checkUserValidity(user);
94 request.setPassword(user.getPassword());
95 }
96 SpringSecurityDigestPasswordValidator validator = new SpringSecurityDigestPasswordValidator(user);
97 passwordCallback.setValidator(validator);
98 return;
99 }
100 }
101 else if (callback instanceof TimestampValidationCallback) {
102 TimestampValidationCallback timestampCallback = (TimestampValidationCallback) callback;
103 timestampCallback.setValidator(new DefaultTimestampValidator());
104
105 }
106 else if (callback instanceof CleanupCallback) {
107 SecurityContextHolder.clearContext();
108 return;
109 }
110 throw new UnsupportedCallbackException(callback);
111 }
112
113 private UserDetails loadUserDetails(String username) throws DataAccessException {
114 UserDetails user = userCache.getUserFromCache(username);
115
116 if (user == null) {
117 try {
118 user = userDetailsService.loadUserByUsername(username);
119 }
120 catch (UsernameNotFoundException notFound) {
121 if (logger.isDebugEnabled()) {
122 logger.debug("Username '" + username + "' not found");
123 }
124 return null;
125 }
126 userCache.putUserInCache(user);
127 }
128 return user;
129 }
130
131 private class SpringSecurityDigestPasswordValidator extends PasswordValidationCallback.DigestPasswordValidator {
132
133 private UserDetails user;
134
135 private SpringSecurityDigestPasswordValidator(UserDetails user) {
136 this.user = user;
137 }
138
139 @Override
140 public boolean validate(PasswordValidationCallback.Request request)
141 throws PasswordValidationCallback.PasswordValidationException {
142 if (super.validate(request)) {
143 UsernamePasswordAuthenticationToken authRequest =
144 new UsernamePasswordAuthenticationToken(user, user.getPassword());
145 if (logger.isDebugEnabled()) {
146 logger.debug("Authentication success: " + authRequest.toString());
147 }
148
149 SecurityContextHolder.getContext().setAuthentication(authRequest);
150 return true;
151 }
152 else {
153 return false;
154 }
155 }
156 }
157
158 }