一个应用程序中的 Spring Security OAuth2 身份验证和表单登录
Posted
技术标签:
【中文标题】一个应用程序中的 Spring Security OAuth2 身份验证和表单登录【英文标题】:Spring security OAuth2 authentication and form login in one app 【发布时间】:2016-01-24 08:32:56 【问题描述】:是否可以在一个应用程序中通过 login basic 和 oauth2 结合授权和身份验证?
我的项目基于 jhipster 项目,带有简单的 spring 安全会话登录,现在我需要为移动应用程序添加 oauth2 安全性,看起来这是不可能的。
现在我在工作其中之一时遇到了情况,如果 WebSecurityConfigurerAdapter 的订单号大于 ResourceServerConfiguration,oauth2 可以。这意味着如果 oauth 安全过滤器是第一个。 我在 *** 中阅读了很多内容并尝试了许多解决方案,例如: Spring security oauth2 and form login configuration 对我来说那是行不通的。 现在我知道这与一些安全过滤器冲突有关,但我不知道如何解决它。
如果有人遇到类似问题并且他设法解决了问题,或者知道如何解决或改进问题,我将不胜感激。提前感谢您的帮助:)
@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,我得到有效的访问令牌,但对于会话中使用此令牌的请求,我得到以下结果:
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;
在控制台中写入函数: 匿名用户 真的 [ROLE_ANONYMOUS] 匿名用户
并且应该是user1 真的 [ROLE_USER] 用户1
【问题讨论】:
您能否在 Github 或其他地方发布一个简单但功能齐全的演示应用程序来演示您的问题?谢谢 【参考方案1】:应用程序的 git 网址: https://github.com/rynkowsw/oauth2 是 oauth2 应用 https://github.com/rynkowsw/web-and-oauth2-security 这是 web 和 oauth2 安全应用程序
本应用改编自 jhipster.github.io
要运行应用程序,您需要在 localhost 中有 postgres db,例如在 db 资源文件中:
driver-class-name: org.postgresql.ds.PGSimpleDataSource
url: jdbc:postgresql://localhost:5432/gymapp
name: gymapp
serverName: localhost:5432
username: postgres
password: jaja
测试应用最快的方法是:
http://localhost:8080/oauth/token
headers: Authorization: Basic amhpcHN0ZXJhcHA6bXlTZWNyZXRPQXV0aFNlY3JldA==
basic后面的这个字符串是组合default jhispter oauth secret和clientid base64加密结果
然后
http://localhost:8080/api/account
headers: Authorization: bearer [token from response in first request]
对于同一个数据库,oauth 的结果是: 对于 oauth2 应用程序
login: "user"
password: null
firstName: "User"
lastName: "User"
email: "user@localhost"
activated: true
langKey: "en"
authorities: [1]
0: "ROLE_USER"
-
对于 web + oauth2 安全性:
login: "anonymousUser"
password: null
firstName: "Anonymous"
lastName: "User"
email: "anonymous@localhost"
activated: true
langKey: "en"
authorities: [0]
【讨论】:
你找到答案了吗?以上是关于一个应用程序中的 Spring Security OAuth2 身份验证和表单登录的主要内容,如果未能解决你的问题,请参考以下文章
一个应用程序中的 Spring Security OAuth2 身份验证和表单登录
Tomcat 和 spring-security 中的 Web 应用程序和 REST 服务 SSO
为啥应用程序看不到 Spring Security 中的角色(禁止)
将 Facebook Authentication 集成到 FacebookApp 中的 Spring Security