【问题标题】:Spring cannot configure authorization serverSpring无法配置授权服务器
【发布时间】:2017-08-09 15:00:05
【问题描述】:

我创建了一个简单的授权服务器,但无法对其进行配置。

  1. 启动两个应用程序(8080 用于身份验证服务器,9999 用于客户端)。
  2. 转到localhost:9999/client 并重定向到localhost:8080/login(如预期的那样)。
  3. 用用户/用户填写登录表单。
  4. 被重定向到localhost:9999/client(如预期),但使用Hello, null 而不是Hello, user。

但是,如果我直接去localhost:8080/me,我有{"name":"user"}。如何检索Hello, user?

授权服务器

@RestController
@EnableAuthorizationServer
@SpringBootApplication
public class Application extends WebSecurityConfigurerAdapter {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @GetMapping({ "/user", "/me" })
    public Map<String, String> user(Principal principal) {
        return Collections.singletonMap("name", principal == null ? "null" : principal.getName());
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user").password("user").authorities(AuthorityUtils.NO_AUTHORITIES);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin();
    }
}

应用程序的属性

security:
  oauth2:
    client:
      client-id: clientid
      client-secret: clientsecret
      scope: read,write
      auto-approve-scopes: '.*'

客户

@Configuration
@EnableAutoConfiguration
@EnableOAuth2Sso
@RestController
public class Client {

    @GetMapping("/")
    public String home(Principal principal) {
        return "Hello, " + principal.getName();
    }

    public static void main(String[] args) {
        new SpringApplicationBuilder(Client.class)
                .properties("spring.config.name=client").run(args);
    }

}

客户的属性

server:
  port: 9999
  context-path: /client
security:
  oauth2:
    client:
      client-id: clientid
      client-secret: clientsecret
      access-token-uri: http://localhost:8080/oauth/token
      user-authorization-uri: http://localhost:8080/oauth/authorize
    resource:
      user-info-uri: http://localhost:8080/me

更新:
当一切正常时,我下载了a tutorial,但它的ssoFilter 仅用于OAuth2 身份验证。我只想用loginForm配置它。
我还在 GitHub 上分享了一个临时的 example。我认为用它查找问题会更容易。

【问题讨论】:

  • 您的要求如何?包括标题
  • 只是猜测,根据 UserDetailsS​​ervice 合同,用户必须拥有 GrantedAuthorites 否则会抛出 UsernameNotFoundException,尝试给您的用户一个角色。
  • @OrtwinAngermeier,不幸的是,这不起作用。

标签: java spring spring-boot spring-security spring-security-oauth2


【解决方案1】:

有不同的端口9999 8080这将导致当它从不同的域请求资源时跨域 HTTP请求,或端口而不是第一个资源本身服务的端口。

关于HTTP access control (CORS)

的更多详情

春天官方网站Enabling Cross Origin Requests for a RESTful Web Service有泥煤很好的例子

我建议通过实现 Filter 接口对您的应用进行 CORS 过滤。

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {

    public CorsFilter() {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "*"); //for production add only origins which should be allowed to access now for demo purposes this accepts all.
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); //i would reduce this method list if not all methods used this is added just for demo purposes
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization");

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, res);
        }
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {
    }
}

如果您使用的是 Spring Boot 应用程序,请务必包括您的新过滤器在 在组件扫描中创建的包。

如果您使用“web.xml”进行配置:

然后添加过滤器

<filter>
    <filter-name>CORS</filter-name>
    <filter-class>com.mycompany.CorsFilter</filter-class>
</filter>

选项A在你的servlet上添加映射

<filter-mapping>
        <filter-name>CORS</filter-name>
        <servlet-name>MyServlet</servlet-name>
</filter-mapping>

选项B为所有应用添加过滤器:

<filter-mapping>
        <filter-name>CORS</filter-name>
        <url-pattern>/*</url-pattern> <!--this will add cors on all apps-->
</filter-mapping>

【讨论】:

  • 过滤器在登录服务器上过滤,但似乎不是解决方案。我还有Hello, null。
  • 安装 fiddler 或其他可以打印 HTTP 通信的工具。或者只需按 F12 按钮使用 Web 开发人员工具,然后转到网络选项卡并查看您的请求是如何处理的,所有 HTTP 数据包都应该有 200 个状态代码。请你做截图然后我可以看到发生了什么。如果你没有改变来解决这个问题,我仍然相信 CORS 问题。
  • 我安装了 Fiddler。以下是截图:without filter、with filter。除了 favicon 之外,它们似乎是相同的。
  • 我也忘了提到问题没有解决。我授予赏金是因为它快过期了,我认为这真的是因为 CORS。
【解决方案2】:

用户详细信息由org.springframework.cloud.security.oauth2.resource.UserInfoTokenServices 加载,因此值得在其中添加一个断点以查看它从您的 /me 端点得到什么。

此类仅提取基本用户详细信息,实际上查看代码似乎设置了 ROLE_USER 的硬编码角色,因此建议您创建自己的实现来正确设置您的OAuth2Authentication用户。

【讨论】:

    【解决方案3】:

    因为您的身份验证服务器和客户端都由同一主机 (localhost) 提供服务,您的网络浏览器可能会混淆哪个 http 端点属于哪个 http cookie。

    尝试将一个指定为127.0.0.1,另一个指定为localhost,以便您的浏览器将 http cookie 关联到其正确的端点。

    【讨论】:

    • 还是不行。当一切正常时我下载了a tutorial,但我可以使用localhost 访问它。
    【解决方案4】:

    稍微更改了您的代码,它对我来说在本地工作。

    @EnableOAuth2Client
    @RestController
    @EnableAuthorizationServer
    @SpringBootApplication
    @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
    public class Application extends WebSecurityConfigurerAdapter {
    
    @Autowired
    OAuth2ClientContext oauth2ClientContext;
    
    
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    
    @GetMapping({"/user", "/me"})
    public Map<String, String> user(Principal principal) {
        Authentication authentication = SecurityContextHolder.getContext()
                .getAuthentication();
        return Collections.singletonMap("name", principal == null ? "null" : principal.getName());
    }
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user").password("user").authorities(AuthorityUtils.NO_AUTHORITIES);
    }
    
    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
        @Override
        public void configure(HttpSecurity http) throws Exception {
            // @formatter:off
            http.antMatcher("/me").authorizeRequests().anyRequest().authenticated();
            // @formatter:on
        }
    }
    
    @Bean
    public FilterRegistrationBean oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(filter);
        registration.setOrder(-100);
        return registration;
    }
    
    private Filter authFilter(ClientResources client, String path) {
        OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(
                path);
        OAuth2RestTemplate template = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
        filter.setRestTemplate(template);
        UserInfoTokenServices tokenServices = new UserInfoTokenServices(
                client.getResource().getUserInfoUri(), client.getClient().getClientId());
        tokenServices.setRestTemplate(template);
        filter.setTokenServices(tokenServices);
        return filter;
        }
    }
    
    class ClientResources {
    
    @NestedConfigurationProperty
    private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();
    
    @NestedConfigurationProperty
    private ResourceServerProperties resource = new ResourceServerProperties();
    
    public AuthorizationCodeResourceDetails getClient() {
        return client;
    }
    
    public ResourceServerProperties getResource() {
        return resource;
        }
    }
    

    你需要注册一个 authenticationTokenFilter,不需要注册 ssoFilter。

    【讨论】:

    • 我的授权服务器不是OAuth2客户端,只想使用简单的表单登录。
    猜你喜欢
    • 2016-12-12
    • 2017-11-30
    • 2015-08-26
    • 2016-08-12
    • 2015-11-19
    • 2015-03-31
    • 1970-01-01
    • 2018-08-24
    • 2015-04-24
    相关资源
    最近更新 更多