将资源服务器添加到现有的JSF / Spring安全应用程序

时间:2018-12-13 20:18:47

标签: java spring spring-security oauth-2.0 spring-oauth2

当前,我们已经使用oauth2.0协议和密码流实现了集中式授权服务器。我会将用户,pwd,secret和clientID发布到auth服务器端点,找回JWT并上路。

我目前在此现有“客户端”应用程序中拥有的是一些Spring Security样板,可根据角色配置流量。

我需要做的是(我认为)-登录该应用程序时,我将收到一个令牌。该令牌存储在会话中,每当我访问该应用程序上的页面时,我都会确认该令牌仍然有效,或者刷新该令牌以使我可以继续访问受保护的内容。

我假设我需要执行以下操作:

  1. 将资源服务器添加到我现有的应用程序(@EnableResourceServer)中,以使流量流经oauth2.0进程。
  2. 配置所述资源服务器(类似于我的WebSecurityConfigurerAdapter配置类),以便检查令牌
  3. 保持其他所有内容(角色,文件结构等)不变

我该如何使用Spring?我看过教程,大多数内容都是相同的家庭资源和身份验证服务器解决方案,或者对如何配置某些东西的解释很少。

属性文件:

security.oauth2.client.client-id= clientid
security.oauth2.client.client-secret= clientsecret
security.oauth2.client.access-token-uri= http://localhost:1234/oauth/token
security.oauth2.client.user-authorization-uri= http://localhost:1234/oauth/authorize

security.oauth2.resource.service-id=res_id
security.oauth2.resource.user-info-uri= http://localhost:1234/me
security.oauth2.resource.token-info-uri= http://localhost:1234/oauth/check_token
security.oauth2.resource.token-type= Bearer

当前的WebSecurityConfigurerAdapter:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@ComponentScan("com.testproj")
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomAuthenticationProvider authProvider;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // Authentication control
        http
            .authorizeRequests()
            .antMatchers("/login.xhtml**").permitAll() // All everyone to see login page
            .antMatchers("/login").permitAll() // All everyone to see login page
            .antMatchers("/views/**").hasAnyAuthority("USER", "ADMIN")
            .antMatchers("/javax.faces.resource/**").permitAll() // All everyone to see resources
            .antMatchers("/resources/**").permitAll() // All everyone to see resources
            .anyRequest().authenticated(); // Ensure any request to application is authenticated

        // Login control
        http
            .formLogin()
                .loginPage("/login.xhtml")
                .loginProcessingUrl("/login")
                .successForwardUrl("/views/home.xhtml")
                .failureUrl("/login.xhtml?error=true");

        // not needed as JSF 2.2 is implicitly protected against CSRF
        http
            .csrf().disable();
    } 

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authProvider);
    }   
} 

自定义身份验证器:

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private AppUserDAO appUserDAO;

    private String accessTokenUri = "http://localhost:1234/oauth/token";
    private String clientId = "clientid";
    private String clientSecret = "clientsecret";

    public AccessTokenProvider userAccessTokenProvider() {
        ResourceOwnerPasswordAccessTokenProvider accessTokenProvider = new ResourceOwnerPasswordAccessTokenProvider();
        return accessTokenProvider;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        final String username = authentication.getName();
        final String password = authentication.getCredentials().toString();

        List<String> scopes = new ArrayList<String>();
        scopes.add("read");

        final ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails();

        resource.setUsername(username);
        resource.setPassword(password);
        resource.setAccessTokenUri(accessTokenUri);
        resource.setClientId(clientId);
        resource.setClientSecret(clientSecret);
        resource.setGrantType("password");
        resource.setScope(scopes);

        // Generate an access token
        final OAuth2RestTemplate template = new OAuth2RestTemplate(resource, new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest()));
        template.setAccessTokenProvider(userAccessTokenProvider());

        OAuth2AccessToken accessToken = null;

        try {
            accessToken = template.getAccessToken();
            System.out.println("Grabbed access token from " + accessTokenUri);
        }
        catch (OAuth2AccessDeniedException e) {
            if (e.getCause() instanceof ResourceAccessException) {
                final String errorMessage = String.format(
                        "While authenticating user '%s': " + "Unable to access accessTokenUri '%s'.", username,
                        accessTokenUri);
                throw new AuthenticationServiceException(errorMessage, e);
            }
            throw new BadCredentialsException(String.format("Access denied for user '%s'.", username), e);
        }
        catch (OAuth2Exception e) {
            throw new AuthenticationServiceException(
                    String.format("Unable to perform OAuth authentication for user '%s'.", username), e);
        }

        // Determine roles for user
        List<GrantedAuthority> grantList = ...

        // Create custom user for the principal
        User user = .....

        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, null /*dont store password*/, grantList);

        return token;
    }

    @Override
    public  boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}

资源服务器:

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    ????
}

修改

因此,我将httpsecurity配置移到了资源服务器配置中,当我尝试进入/views/home.xhtml页面时,出现“访问被拒绝”的消息。

日志表明主体是匿名的(与securityconfig中的不一样)

Secure object: FilterInvocation: URL: /views/home.xhtml; Attributes: [#oauth2.throwOnError(hasAuthority('USER'))]
Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@fc4a062: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true;

编辑2

这可能是关于oauth2可以实现的问题,因为我有点发疯。

根据oauth规范,共有4件-身份验证服务器,资源服务器,客户端和资源所有者

我想我的问题是-我真的可以结合资源服务器和客户端吗?资源所有者将登录到我的应用程序(客户端),从auth服务器获得授权,以查看其在资源服务器/客户端上的资源。

我真的希望我能找到一个很好的例子-看起来如此明确和普遍。

0 个答案:

没有答案