【问题标题】:Spring Social /connect return HTTP 404Spring Social /connect 返回 HTTP 404
【发布时间】:2016-05-25 22:50:11
【问题描述】:

当我尝试打开 /connect/linkedin 时,Spring 找不到 html 视图并且我得到 404。在对that post 的引用中,我仔细检查了 webapp 文件夹中的路径。这是我的 SpringSocialConfig

@Configuration
@EnableSocial
public class SocialConfig implements SocialConfigurer {

    @Inject
    private DataSource dataSource;

    @Override
    public void addConnectionFactories(ConnectionFactoryConfigurer connectionFactoryConfigurer, Environment environment) {
        connectionFactoryConfigurer.addConnectionFactory(new LinkedInConnectionFactory("xxxxxx", "xxxxxx"));
    }

    @Override
    public UserIdSource getUserIdSource() {
        return new UserIdSource() {
            @Override
            public String getUserId() {
                Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
                if (authentication == null) {
                    throw new IllegalStateException("Unable to get a ConnectionRepository: no user signed in");
                }
                return authentication.getName();
            }
        };
    }

    @Bean
    public ConnectController connectController(ConnectionFactoryLocator connectionFactoryLocator, ConnectionRepository connectionRepository) {
        return new ConnectController(connectionFactoryLocator, connectionRepository);
    }


    @Bean
    @Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
    public LinkedIn linkedin(ConnectionRepository repository) {
        Connection<LinkedIn> connection = repository.findPrimaryConnection(LinkedIn.class);
        return connection != null ? connection.getApi() : null;
    }

    @Override
    public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
        return new JdbcUsersConnectionRepository(dataSource, connectionFactoryLocator, Encryptors.noOpText());
    }
}

我的 HomeController 带有 /linkedin 映射处理程序

@Inject
private ConnectionRepository connectionRepository;

@Inject
private LinkedIn linkedIn;

@Inject
public HomeController(LinkedIn linkedIn) {
    this.linkedIn = linkedIn;
}

@RequestMapping(value = "/linkedin", method = RequestMethod.GET)
public String home(Principal currentUser, Model model) {
    Connection<LinkedIn> connection = connectionRepository.findPrimaryConnection(LinkedIn.class);
    if (connection == null) {
        return "redirect:/connect/linkedin";
    }
    model.addAttribute("profile", connection.getApi().profileOperations().getUserProfileFull());
    return "linkedin/profile";
}

还有我的带有视图的 WEBAPP 文件夹

正如我在日志中看到的那样,发生了一些事情并且发现了 /connect/* 映射。

[localhost-startStop-1] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}],methods=[POST]}" onto public org.springframework.web.servlet.view.RedirectView org.springframework.social.connect.web.ConnectController.connect(java.lang.String,org.springframework.web.context.request.NativeWebRequest)
[localhost-startStop-1] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}],methods=[GET]}" onto public java.lang.String org.springframework.social.connect.web.ConnectController.connectionStatus(java.lang.String,org.springframework.web.context.request.NativeWebRequest,org.springframework.ui.Model)
[localhost-startStop-1] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect],methods=[GET]}" onto public java.lang.String org.springframework.social.connect.web.ConnectController.connectionStatus(org.springframework.web.context.request.NativeWebRequest,org.springframework.ui.Model)
[localhost-startStop-1] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}],methods=[GET],params=[oauth_token]}" onto public org.springframework.web.servlet.view.RedirectView org.springframework.social.connect.web.ConnectController.oauth1Callback(java.lang.String,org.springframework.web.context.request.NativeWebRequest)
[localhost-startStop-1] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}],methods=[GET],params=[code]}" onto public org.springframework.web.servlet.view.RedirectView org.springframework.social.connect.web.ConnectController.oauth2Callback(java.lang.String,org.springframework.web.context.request.NativeWebRequest)
[localhost-startStop-1] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}],methods=[GET],params=[error]}" onto public org.springframework.web.servlet.view.RedirectView org.springframework.social.connect.web.ConnectController.oauth2ErrorCallback(java.lang.String,java.lang.String,java.lang.String,java.lang.String,org.springframework.web.context.request.NativeWebRequest)
[localhost-startStop-1] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}],methods=[DELETE]}" onto public org.springframework.web.servlet.view.RedirectView org.springframework.social.connect.web.ConnectController.removeConnections(java.lang.String,org.springframework.web.context.request.NativeWebRequest)
[localhost-startStop-1] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}/{providerUserId}],methods=[DELETE]}" onto public org.springframework.web.servlet.view.RedirectView org.springframework.social.connect.web.ConnectController.removeConnection(java.lang.String,java.lang.String,org.springframework.web.context.request.NativeWebRequest)
[local

我正在使用 Thymeleaf 3.0

@Bean
public ViewResolver viewResolver() {
    ThymeleafViewResolver resolver = new ThymeleafViewResolver();
    resolver.setTemplateEngine(templateEngine());
    resolver.setCharacterEncoding("UTF-8");
    resolver.setContentType("text/html; charset=UTF-8");
    return resolver;
}

@Bean
public TemplateEngine templateEngine() {
    SpringTemplateEngine engine = new SpringTemplateEngine();
    engine.setEnableSpringELCompiler(true);
    engine.setTemplateResolver(templateResolver());
    engine.addDialect(new SpringSecurityDialect());
    return engine;
}

 private ITemplateResolver templateResolver() {
        SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
        resolver.setApplicationContext(applicationContext);
        resolver.setPrefix("/views/");
        resolver.setSuffix(".html");
        resolver.setTemplateMode(TemplateMode.HTML);
        resolver.setCharacterEncoding("UTF-8");
        resolver.setCacheable(Boolean.parseBoolean(THYMELEAF_CACHE));
        return resolver;
    }

调度程序配置

public class WebAppInitializer implements WebApplicationInitializer {

    private final String APP_SERVLET_NAME = "x";
    private final String DISPLAY_NAME = "App";

    @Override
    public void onStartup(ServletContext container) {
        container.addListener(new ContextLoaderListener(getContext()));
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("utf-8");
        characterEncodingFilter.setForceEncoding(true);

        container.addFilter("charEncodingFilter", characterEncodingFilter).addMappingForUrlPatterns(null, false, "/*");
        container.addFilter("securityFilter", new DelegatingFilterProxy("springSecurityFilterChain")).addMappingForUrlPatterns(null, false, "/*");
        container.addFilter("apiFilter", new DelegatingFilterProxy("apiExceptionHandler"));
        container.addFilter("hidden", new HiddenHttpMethodFilter());

        AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
        dispatcherServlet.register(ServletConfig.class);

        ServletRegistration.Dynamic dispatcher = container.addServlet(APP_SERVLET_NAME, new DispatcherServlet(dispatcherServlet));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }

    private AnnotationConfigWebApplicationContext getContext() {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(JPARepositoryConfig.class,
                ThymeleafConfig.class,
                WebSecurityConfig.class,
                SocialConfig.class,
                MailConfig.class,
                MongoRepositoryConfig.class,
                ServiceConfig.class,
                CacheConfig.class);

        rootContext.setDisplayName(DISPLAY_NAME);
        return rootContext;
    }

我在 Spring Social 的 Connection Controller 中设置了断点,并且调用了非映射方法。所以我认为应用配置很混乱。

编辑 我有错误的spring servlet配置。我将 spring 社交控制器注册为 root servlet。

【问题讨论】:

  • 嘿@Jakub,你可以尝试将debug log level 设置为spring controller 吗? log4j.logger.controller=调试,控制台
  • 你能在 GitHub 上创建一个简单的项目来复制这个错误吗?帮助你会更容易。

标签: spring spring-mvc spring-social spring-social-linkedin


【解决方案1】:

我认为问题在于您的视图的位置。

您在src/main/webapp 下拥有它,而spring 正在src/main/resources 下搜索视图。

要么将所有 html 文件移动到 src/main/resources/views,要么更改配置以便 spring 在 src/main/webapp/views 下搜索。

检查此Example 配置与您的配置相似,但视图位于src/main/resources 文件夹下。

【讨论】:

    【解决方案2】:

    我猜你的 application.properties 文件中可能需要spring.social.auto-connection-views=true

    【讨论】:

    • 我根本没有 application.properties 文件。我使用的是 Spring MVC,而不是 Boot。
    • 好吧,如果设置为 true,“redirect:/connect/linkedin”通常会重定向到这些视图,如果您没有设置此标志,我想您需要提供自己的视图才能建立连接或以某种方式将此标志设置为 true(我不是 Spring MVC 用户,因此无法提供帮助)
    • 很确定您只需要提供自己的视图即可重定向到您的社交媒体以登录,因为这样的重定向不应该起作用(它应该仅在带有提供一些隐藏视图的标志的引导时起作用和配置)。
    • 如您所见,我提供了自定义视图 (webapp/views/connect/*) 也许我应该将这些文件移到其他地方?
    • 您重定向到“connect/linkedin”,但在 (webapp/views/connect/*) 中您没有查看“linkedin”,这就是您获得 404 imo 的原因。
    【解决方案3】:

    我知道已经很久了,但我想我找到了解决这个问题的方法。

    问题是,您的 spring 配置发现 'ConnectController' 作为 bean,但它没有映射为 Controller。另外,我检查了 ConnectController 类的来源。原来它是根据前缀和providerId构建视图名称的。

    按照这个答案:https://stackoverflow.com/a/19699607/4544269

    我继承了 ConnectController,并覆盖了“connectView”和“connectedView”,现在指向 WEB-INF 文件夹中的 Freemarkers 模板。

    @Controller
    public class CustomConnectController extends ConnectController{
    
        @Autowired
        public CustomConnectController(
                ConnectionFactoryLocator connectionFactoryLocator,
                ConnectionRepository connectionRepository) {
            super(connectionFactoryLocator, connectionRepository);
        }
    
        @Override
        protected String connectedView(String providerId){
            return "connect/facebookConnected";
        }
    
        @Override
        protected String connectView(String providerId) {
            return "connect/facebookConnect";
        }
    
       }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-07
      • 2013-11-02
      • 1970-01-01
      • 2019-10-22
      • 1970-01-01
      • 2013-11-10
      • 2022-11-11
      相关资源
      最近更新 更多