And*_*erk 32 spring-security single-sign-on spring-social spring-boot spring-security-oauth2
我正在使用Spring Boot + Spring Security OAuth2应用程序,我认为该应用程序的灵感来自Dave Syer的示例.应用程序配置为OAuth2授权服务器,单个公共客户端使用资源所有者密码凭据流.成功的令牌配置为JWT.
公共Angular客户端向/ oauth/token发送一个POST请求,其中包含一个包含客户端ID和密码的基本auth头(这是让客户端进行身份验证的最简单方法,即使秘密不是私有的).请求正文包含用户名,密码和授予类型"密码".
除了作为身份验证服务器之外,该应用程序还是用户,团队和组织的RESTful资源服务器.
我正在尝试使用Spring Social添加额外的SSO身份验证流程.我已经将Spring Social配置为通过/ auth/[provider]通过外部提供程序进行身份验证; 但是,以下请求不再正确设置SecurityContext.可能是Spring Security OAuth服务器或客户端覆盖了SecurityContext?
如果我可以在Spring Social流程之后正确设置SecurityContext,我有一个新的TokenGranter,允许新的授权类型"social",它将检查SecurityContextHolder以获得预先认证的用户.
我对SecurityContext的特定问题的解决方案感兴趣(我认为这是Spring OAuth +社交集成的问题),或者是与外部提供程序进行身份验证以及从我们自己的auth服务器获取有效JWT的不同方法.
谢谢!
rba*_*uso 12
我在JHipster生成的Web应用程序上遇到了类似的问题.最后我决定SocialAuthenticationFilter
选择Spring Social(通过SpringSocialConfigurer
).成功进行社交登录后,服务器会自动生成并返回"自己的"访问令牌,方法是重定向到客户端应用程序.
这是我的尝试:
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter implements EnvironmentAware {
//...
@Inject
private AuthorizationServerTokenServices authTokenServices;
@Override
public void configure(HttpSecurity http) throws Exception {
SpringSocialConfigurer socialCfg = new SpringSocialConfigurer();
socialCfg
.addObjectPostProcessor(new ObjectPostProcessor<SocialAuthenticationFilter>() {
@SuppressWarnings("unchecked")
public SocialAuthenticationFilter postProcess(SocialAuthenticationFilter filter){
filter.setAuthenticationSuccessHandler(
new SocialAuthenticationSuccessHandler(
authTokenServices,
YOUR_APP_CLIENT_ID
)
);
return filter;
}
});
http
//... lots of other configuration ...
.apply(socialCfg);
}
}
Run Code Online (Sandbox Code Playgroud)
和SocialAuthenticationSuccessHandler
班级:
public class SocialAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
public static final String REDIRECT_PATH_BASE = "/#/login";
public static final String FIELD_TOKEN = "access_token";
public static final String FIELD_EXPIRATION_SECS = "expires_in";
private final Logger log = LoggerFactory.getLogger(getClass());
private final AuthorizationServerTokenServices authTokenServices;
private final String localClientId;
public SocialAuthenticationSuccessHandler(AuthorizationServerTokenServices authTokenServices, String localClientId){
this.authTokenServices = authTokenServices;
this.localClientId = localClientId;
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
log.debug("Social user authenticated: " + authentication.getPrincipal() + ", generating and sending local auth");
OAuth2AccessToken oauth2Token = authTokenServices.createAccessToken(convertAuthentication(authentication)); //Automatically checks validity
String redirectUrl = new StringBuilder(REDIRECT_PATH_BASE)
.append("?").append(FIELD_TOKEN).append("=")
.append(encode(oauth2Token.getValue()))
.append("&").append(FIELD_EXPIRATION_SECS).append("=")
.append(oauth2Token.getExpiresIn())
.toString();
log.debug("Sending redirection to " + redirectUrl);
response.sendRedirect(redirectUrl);
}
private OAuth2Authentication convertAuthentication(Authentication authentication) {
OAuth2Request request = new OAuth2Request(null, localClientId, null, true, null,
null, null, null, null);
return new OAuth2Authentication(request,
//Other option: new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), "N/A", authorities)
new PreAuthenticatedAuthenticationToken(authentication.getPrincipal(), "N/A")
);
}
private String encode(String in){
String res = in;
try {
res = UriUtils.encode(in, GeneralConstants.ENCODING_UTF8);
} catch(UnsupportedEncodingException e){
log.error("ERROR: unsupported encoding: " + GeneralConstants.ENCODING_UTF8, e);
}
return res;
}
}
Run Code Online (Sandbox Code Playgroud)
这样,您的客户端应用程序将通过重定向接收您的Web应用程序的访问令牌/#/login?access_token=my_access_token&expires_in=seconds_to_expiration
,只要您设置相应REDIRECT_PATH_BASE
的SocialAuthenticationSuccessHandler
.
我希望它有所帮助.
首先,我强烈建议您放弃这种用例的密码授予.
公共客户端(JavaScript,已安装的应用程序)无法保密其客户机密,这就是为什么它们不能被分配一个:任何检查您的JavaScript代码的访问者都可以发现该秘密,从而实现您拥有的相同身份验证页面,将您的用户密码存储在这个过程.
在隐性补助已建立正是为了你在做什么.
使用基于重定向的流具有将身份验证机制留给授权服务器的优势,而不是让每个应用程序都有一部分:这主要是单点登录(SSO)的定义.
话虽如此,您的问题与我刚才回答的问题紧密相关:拥有Spring的OAuth2服务器以及第三方OAuth提供商
总结答案:
最后,它是关于授权服务器如何保护AuthorizationEndpoint:/ oauth/authorize.由于您的授权服务器可以工作,因此您已经有一个扩展WebSecurityConfigurerAdapter的配置类,它使用formLogin处理/ oauth/authorize的安全性.这就是你需要整合社交内容的地方.
您根本无法使用密码授予您要实现的目标,您必须将公共客户端重定向到授权服务器.然后,授权服务器将重定向到社交登录,作为/oauth/authorize
端点的安全机制.
归档时间: |
|
查看次数: |
8589 次 |
最近记录: |