简体   繁体   English

Spring安全性OAuth2身份验证和表单登录在一个应用程序中

[英]Spring security OAuth2 authentication and form login in one app

Is it possible to combine authoryzation and authentication by login basic and by oauth2 in one application? 是否可以通过login basic和oauth2在一个应用程序中组合authoryzation和身份验证?

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. 我的项目基于jhipster项目,简单的弹簧安全会话登录,现在我需要为移动应用程序添加oauth2安全性,看起来它是不可能的。

Now i have situation when work one of them, oauth2 ok if WebSecurityConfigurerAdapter had bigger order number than ResourceServerConfiguration. 现在我有工作其中一个的情况,oauth2确定如果WebSecurityConfigurerAdapter的订单号比ResourceServerConfiguration更大。 That's mean if oauth security filter is first. 这意味着如果首先是oauth安全过滤器。 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. 我在stackoverflow中阅读了很多内容并尝试了许多解决方案,例如: Spring security oauth2和表单登录配置,对我来说这是不行的。
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();


    }
}

}

For this settings WebSecurityConfigurerAdapter session work correctly. 对于此设置,WebSecurityConfigurerAdapter会话正常工作。 For OAuth after correctly authorizatization i get valid acces token, but for request with this token from session i get this result: 对于正确授权后的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;
}

function write in console: anonymousUser true [ROLE_ANONYMOUS] anonymousUser 函数在控制台中写入:anonymousUser true [ROLE_ANONYMOUS] anonymousUser

and should be user1 true [ROLE_USER] user1 并且应该是user1 true [ROLE_USER] user1

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 应用程序git urls: https//github.com/rynkowsw/oauth2它是oauth2 app https://github.com/rynkowsw/web-and-oauth2-security这是web和oauth2安全应用程序

This app are adapted from jhipster.github.io 这个应用程序改编自jhipster.github.io

to run app you need have postgres db in localhost, like in db resource file: 要运行应用程序,您需要在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

To test app the fastest way is: 要以最快的方式测试应用程序:

 http://localhost:8080/oauth/token
 headers:  Authorization: Basic amhpcHN0ZXJhcHA6bXlTZWNyZXRPQXV0aFNlY3JldA==

this string after basic is combination default jhispter oauth secret and clientid base64 encrypt result 这个字符串基本上是组合默认的jhispter oauth secret和clientid base64加密结果

then 然后

  http://localhost:8080/api/account
  headers:  Authorization: bearer [token from response in first request]

For this same db, result for oauth are: for oauth2 app 对于同一个db,oauth的结果是:for oauth2 app

{
 login: "user"
 password: null
 firstName: "User"
 lastName: "User"
 email: "user@localhost"
 activated: true
 langKey: "en"
 authorities: [1]
 0:  "ROLE_USER"
 -
}

for web + oauth2 security: 对于web + oauth2安全性:

 {
  login: "anonymousUser"
  password: null
  firstName: "Anonymous"
  lastName: "User"
  email: "anonymous@localhost"
  activated: true
  langKey: "en"
  authorities: [0]
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM