Spring security OAuth2 身份验证和表单登录在一个应用程序中 [英] Spring security OAuth2 authentication and form login in one app
问题描述
是否可以在一个应用程序中通过 login basic 和 oauth2 将授权和身份验证结合起来?
Is it possible to combine authoryzation and authentication by login basic and by oauth2 in one application?
我的项目基于 jhipster 项目,使用简单的 spring 安全会话登录,现在我需要为移动应用程序添加 oauth2 安全性,看起来这是不可能的.
My project is based on jhipster project with simple spring security session login, now i need add oauth2 security for mobile app and it's look like it is not possible.
现在我遇到了工作其中之一的情况,如果 WebSecurityConfigurerAdapter 的订单号大于 ResourceServerConfiguration,则 oauth2 可以.这意味着如果 oauth 安全过滤器是第一个.我在stackoverflow中阅读了很多内容并尝试了许多解决方案,例如:Spring 安全 oauth2 和表单登录配置 对我来说这是一个不工作.
现在我知道这与一些安全过滤器冲突有关,但我不知道如何解决它.
Now i have situation when work one of them, oauth2 ok if WebSecurityConfigurerAdapter had bigger order number than ResourceServerConfiguration. That's mean if oauth security filter is first.
I read a lot in stackoverflow and try many solution like:
Spring security oauth2 and form login configuration for me thats one don't work.
Now i know that is related with some security filter conflict but i dont know how to fix it.
如果有人遇到类似的问题并且他设法解决了,或者知道如何解决或改善问题,我将不胜感激.预先感谢您的帮助:)
if someone had a similar problem and he managed to do it, or know how to get around or make it better I will be grateful for the information. Thanks in advance for your help :)
@Configuration
@EnableWebSecurity
public class SecurityOauth2Configuration extends WebSecurityConfigurerAdapter {
@Inject
private UserDetailsService userDetailsService;
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/scripts/**/*.{js,html}")
.antMatchers("/bower_components/**")
.antMatchers("/i18n/**")
.antMatchers("/assets/**")
.antMatchers("/swagger-ui/index.html")
.antMatchers("/api/register")
.antMatchers("/api/activate")
.antMatchers("/api/account/reset_password/init")
.antMatchers("/api/account/reset_password/finish")
.antMatchers("/test/**");
}
@Configuration
@EnableAuthorizationServer
public static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
private static final String OAUTH_SECURITY = "jhipster.security.authentication.oauth.";
private static final String CLIENTID = "clientid";
private static final String SECRET = "secret";
private static final String TOKEN_VALIDATION_TIME = "tokenValidityInSeconds";
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("isAnonymous() || hasAuthority('"+AuthoritiesConstants.USER+"')").checkTokenAccess("hasAuthority('"+AuthoritiesConstants.USER+"')");
}
@Inject
private Environment env;
@Inject
private DataSource dataSource;
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.tokenStore(tokenStore())
;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient(env.getProperty(OAUTH_SECURITY + CLIENTID))
.scopes("read", "write")
.authorities(AuthoritiesConstants.ADMIN, AuthoritiesConstants.USER)
.authorizedGrantTypes("password", "refresh_token")
.secret(env.getProperty(OAUTH_SECURITY + SECRET))
.accessTokenValiditySeconds(env.getProperty(OAUTH_SECURITY + TOKEN_VALIDATION_TIME, Integer.class, 18000));
}
}
@Configuration
@Order(1)
public static class SecurityWebConfiguration extends WebSecurityConfigurerAdapter {
@Inject
private Environment env;
@Inject
private AjaxAuthenticationSuccessHandler ajaxAuthenticationSuccessHandler;
@Inject
private AjaxAuthenticationFailureHandler ajaxAuthenticationFailureHandler;
@Inject
private AjaxLogoutOauthSuccessHandler ajaxLogoutSuccessHandler;
@Inject
private RememberMeServices rememberMeServices;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable().authorizeRequests()
.and()
.formLogin()
.loginProcessingUrl("/api/authentication")
.successHandler(ajaxAuthenticationSuccessHandler)
.failureHandler(ajaxAuthenticationFailureHandler)
.usernameParameter("j_username")
.passwordParameter("j_password")
.permitAll()
.and()
.rememberMe()
.rememberMeServices(rememberMeServices)
.key(env.getProperty("jhipster.security.rememberme.key"))
.and()
.logout()
.logoutUrl("/api/logout")
.logoutSuccessHandler(ajaxLogoutSuccessHandler)
.deleteCookies("JSESSIONID")
.permitAll()
.and()
.exceptionHandling()
;
}
}
@Order(2)
@Configuration
@EnableResourceServer
public static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Inject
private Http401UnauthorizedEntryPoint authenticationEntryPoint;
@Inject
private AjaxLogoutOauthSuccessHandler ajaxLogoutSuccessHandler;
@Override
public void configure(HttpSecurity http) throws Exception {
ContentNegotiationStrategy contentNegotiationStrategy = http.getSharedObject(ContentNegotiationStrategy.class);
if (contentNegotiationStrategy == null) {
contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
}
MediaTypeRequestMatcher preferredMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy,
MediaType.APPLICATION_FORM_URLENCODED,
MediaType.APPLICATION_JSON,
MediaType.MULTIPART_FORM_DATA);
http
.authorizeRequests()
.and()
.anonymous()
.disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.httpBasic()
.and()
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.defaultAuthenticationEntryPointFor(authenticationEntryPoint, preferredMatcher)
.and()
.authorizeRequests()
.antMatchers("/api/**").fullyAuthenticated();
}
}
}
对于此设置,WebSecurityConfigurerAdapter 会话正常工作.对于正确授权后的 OAuth,我得到有效的访问令牌,但对于来自会话的此令牌的请求,我得到以下结果:
For this settings WebSecurityConfigurerAdapter session work correctly. For OAuth after correctly authorizatization i get valid acces token, but for request with this token from session i get this result:
public static String getCurrentLogin() {
SecurityContext securityContext = SecurityContextHolder.getContext();
Authentication authentication = securityContext.getAuthentication();
UserDetails springSecurityUser = null;
String userName = null;
if(authentication != null) {
if (authentication.getPrincipal() instanceof UserDetails) {
springSecurityUser = (UserDetails) authentication.getPrincipal();
userName = springSecurityUser.getUsername();
} else if (authentication.getPrincipal() instanceof String) {
userName = (String) authentication.getPrincipal();
}
}
System.out.println(userName); // show anonymousUser
System.out.println(authentication.isAuthenticated()); //show true
System.out.println(authentication.getAuthorities()); //show [ROLE_ANONYMOUS]
System.out.println(userName); //show anonymousUser
return userName;
}
在控制台中写入函数:匿名用户真的[角色_匿名]匿名用户
function write in console: anonymousUser true [ROLE_ANONYMOUS] anonymousUser
并且应该是 user1真的[ROLE_USER]用户 1
and should be user1 true [ROLE_USER] user1
推荐答案
应用 git url:https://github.com/rynkowsw/oauth2 这是 oauth2 应用https://github.com/rynkowsw/web-and-oauth2-security这是网络和 oauth2 安全应用程序
The apps git urls: https://github.com/rynkowsw/oauth2 it is oauth2 app https://github.com/rynkowsw/web-and-oauth2-security this is web and oauth2 security app
本应用改编自 jhipster.github.io
This app are adapted from jhipster.github.io
要运行应用程序,您需要在本地主机中有 postgres db,就像在 db 资源文件中一样:
to run app you need have postgres db in localhost, like in db resource file:
driver-class-name: org.postgresql.ds.PGSimpleDataSource
url: jdbc:postgresql://localhost:5432/gymapp
name: gymapp
serverName: localhost:5432
username: postgres
password: jaja
测试应用最快的方法是:
To test app the fastest way is:
http://localhost:8080/oauth/token
headers: Authorization: Basic amhpcHN0ZXJhcHA6bXlTZWNyZXRPQXV0aFNlY3JldA==
basic 后面的这个字符串是默认 jhispter oauth secret 和 clientid base64 加密结果的组合
this string after basic is combination default jhispter oauth secret and clientid base64 encrypt result
然后
http://localhost:8080/api/account
headers: Authorization: bearer [token from response in first request]
对于同一个数据库,oauth 的结果是:对于 oauth2 应用
For this same db, result for oauth are: for oauth2 app
{
login: "user"
password: null
firstName: "User"
lastName: "User"
email: "user@localhost"
activated: true
langKey: "en"
authorities: [1]
0: "ROLE_USER"
-
}
对于网络 + oauth2 安全性:
for web + oauth2 security:
{
login: "anonymousUser"
password: null
firstName: "Anonymous"
lastName: "User"
email: "anonymous@localhost"
activated: true
langKey: "en"
authorities: [0]
}
这篇关于Spring security OAuth2 身份验证和表单登录在一个应用程序中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!