Spring Boot OAuth2 隐式流 + 表单登录和请求方法“POST"不支持错误

编程入门 行业动态 更新时间:2024-10-22 14:05:03
本文介绍了Spring Boot OAuth2 隐式流 + 表单登录和请求方法“POST"不支持错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

在我的 Spring Boot 应用程序中,我试图配置 OAuth2 隐式流.为此,我正在尝试配置自定义登录表单.

这是我的配置:

@Configuration公共类 WebMvcConfig 扩展了 WebMvcConfigurerAdapter {@覆盖public void configureDefaultServletHandling(DefaultServletHandlerConfigurer 配置器) {配置器.启用();}@覆盖public void addViewControllers(ViewControllerRegistry 注册表) {registry.addViewController("/").setViewName("index");registry.addViewController("/login").setViewName("login");}@覆盖public void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");}}@配置@启用网络安全公共类 WebSecurityConfig 扩展了 WebSecurityConfigurerAdapter {@自动连线私人 SocialAuthenticationSuccessHandler socialAuthenticationSuccessHandler;@自动连线私有 DBUserDetailsS​​ervice userDetailsS​​ervice;@Value("${social.postLogin.url}")私人字符串 postLoginUrl;@覆盖公共无效配置(WebSecurity web)抛出异常{//Spring Security 忽略对 CSS 或 JS 等静态资源的请求//文件.web.ignoring().antMatchers("/static/**");}@覆盖protected void configure(HttpSecurity http) 抛出异常 {//@格式化程序:关闭http.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);//在 SocialAuthenticationFilter 上设置一个自定义的 successHandler最终 SpringSocialConfigurer socialConfigurer = new SpringSocialConfigurer();socialConfigurer.addObjectPostProcessor(new ObjectPostProcessor() {@覆盖public <O extends SocialAuthenticationFilter>O postProcess(O socialAuthenticationFilter){socialAuthenticationFilter.setAuthenticationSuccessHandler(socialAuthenticationSuccessHandler);socialAuthenticationFilter.setPostLoginUrl(postLoginUrl);返回 socialAuthenticationFilter;}});http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests().antMatchers("/oauth/authorize").authenticated()//任何人都可以访问网址.antMatchers("/auth/**").permitAll().antMatchers("/actuator/health").permitAll().antMatchers("/actuator/**").hasAuthority("PERMISSION_READ_ACTUATOR_DATA").antMatchers("/login").permitAll().anyRequest().authenticated().and().formLogin().loginPage("/登录").loginProcessingUrl("/登录").usernameParameter("用户名").passwordParameter("密码").permitAll()//将 SocialAuthenticationFilter 添加到 Spring Security 的过滤器链..and()//应用来自 socialConfigurer 的配置(添加 SocialAuthenticationFilter).apply(socialConfigurer);//@格式化程序:打开}/*** 配置处理认证的认证管理器bean* 请求.*/@覆盖protected void configure(AuthenticationManagerBuilder auth) 抛出异常 {auth.userDetailsS​​ervice(userDetailsS​​ervice).passwordEncoder(new BCryptPasswordEncoder());}@覆盖@豆公共 AuthenticationManager authenticationManagerBean() 抛出异常 {返回 super.authenticationManagerBean();}}@配置公共类 OAuth2ServerConfig {私有静态最终字符串RESOURCE_ID =restservice";@自动连线私有 DBUserDetailsS​​ervice userDetailsS​​ervice;@豆@主要公共 DefaultTokenServices tokenServices() {DefaultTokenServices defaultTokenServices = new DefaultTokenServices();defaultTokenServices.setTokenStore(tokenStore());defaultTokenServices.setSupportRefreshToken(true);返回 defaultTokenServices;}@豆公共 JwtAccessTokenConverter accessTokenConverter() {JwtAccessTokenConverter 转换器 = 新 JwtAccessTokenConverter() {@覆盖公共 OAuth2AccessToken 增强(OAuth2AccessToken accessToken,OAuth2Authentication 认证){DBUserDetails user = (DBUserDetails) authentication.getUserAuthentication().getPrincipal();最终映射additionalInfo = new HashMap();additionalInfo.put("user_id", user.getUser().getId());((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);OAuth2AccessToken EnhancedToken = super.enhance(accessToken, authentication);返回增强令牌;}};转换器.setSigningKey("123");DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();DefaultUserAuthenticationConverter userTokenConverter = new DefaultUserAuthenticationConverter();userTokenConverter.setUserDetailsS​​ervice(userDetailsS​​ervice);accessTokenConverter.setUserTokenConverter(userTokenConverter);转换器.setAccessTokenConverter(accessTokenConverter);返回转换器;}@豆公共令牌商店令牌商店(){返回新的 JwtTokenStore(accessTokenConverter());}@配置@EnableAuthorizationServer受保护的静态类 AuthorizationServerConfiguration 扩展了 AuthorizationServerConfigurerAdapter {@自动连线@Qualifier("authenticationManagerBean")私有 AuthenticationManager authenticationManager;@自动连线私有 TokenStore 令牌存储;@自动连线私人 TokenEnhancer tokenEnhancer;@覆盖public void configure(AuthorizationServerEndpointsConfigurer endpoints) 抛出异常 {//@格式化程序:关闭端点.tokenStore(tokenStore).tokenEnhancer(tokenEnhancer).authenticationManager(this.authenticationManager);//@格式化程序:打开}@覆盖公共无效配置(ClientDetailsS​​erviceConfigurer 客户端)抛出异常 {//@格式化程序:关闭客户.inMemory().withClient("clientapp").authorizedGrantTypes("密码","re​​fresh_token")//.authorizedGrantTypes("隐式").authorities("ROLE_CLIENT").scopes("读", "写").resourceIds(RESOURCE_ID).secret("123456").and().withClient("clientapp1").authorizedGrantTypes("隐式").scopes("读", "写").autoApprove(true);//@格式化程序:打开}}@配置@EnableResourceServer受保护的静态类 ResourceServerConfiguration 扩展了 ResourceServerConfigurerAdapter {@自动连线私有 ResourceServerTokenServices 令牌服务;@覆盖公共无效配置(ResourceServerSecurityConfigurer 资源){//@格式化程序:关闭资源.resourceId(RESOURCE_ID).tokenServices(tokenService);//@格式化程序:打开}@覆盖公共无效配置(HttpSecurity http)抛出异常{//@格式化程序:关闭http.authorizeRequests().antMatchers("/profile/*").authenticated().and().csrf().disable().sessionManagement().sessionCreationPolicy(STATELESS);//@格式化程序:打开}}}

login.html 页面 Thymeleaf 模板:

<html xmlns="www.w3/1999/xhtml" xmlns:th="www.thymeleaf"xmlns:sec="www.thymeleaf/thymeleaf-extras-springsecurity3"><头><title>Spring 安全示例 </title><身体><div th:if="${param.error}">用户名和密码无效.

<div th:if="${param.logout}">您已注销.

<form th:action="@{/login}" method="post"><div><标签>用户名:<input type="text" name="username"/></label></div><div><标签>密码:<input type="password" name="password"/></label></div><div><input type="submit" value="Sign In"/></div></表单></html>

Maven 工件版本:

1.4.0.RELEASE<spring-security-core.version>4.1.3.RELEASE</spring-security-core.version><spring-security-oauth2.version>2.0.11.RELEASE</spring-security-oauth2.version>

现在,当我尝试访问以下网址时:

localhost:8080/oauth/authorize?response_type=implicit&client_id=clientapp1

我已成功重定向到位于 localhost:8080/login 的登录页面,但是当我输入用户名/密码并按登录"按钮时,出现以下错误:

白标错误页面此应用程序没有明确的/error 映射,因此您将其视为后备.2016 年 9 月 24 日星期六 21:19:44 EEST出现意外错误(type=Method Not Allowed,status=405).不支持请求方法POST"

我做错了什么以及如何解决这个问题?

更新

在调试中我可以看到以下输出:

DispatcherServlet 名为dispatcherServlet",处理 [/login] 的 POST 请求2016-09-25 10:04:43 [http-nio-8080-exec-2] 调试 o.s.w.s.m.m.a.RequestMappingHandlerMapping -查找路径/login 的处理程序方法2016-09-25 10:04:43 [http-nio-8080-exec-2] 调试 o.s.w.s.m.m.a.RequestMappingHandlerMapping -没有找到 [/login] 的处理程序方法2016-09-25 10:04:43 [http-nio-8080-exec-2] 调试 o.s.w.s.h.SimpleUrlHandlerMapping -使用处理程序 [org.springframework.web.servlet.mvc.ParameterizableViewController@c85e70] 和 1 个拦截器将 [/login] 映射到 HandlerExecutionChain2016-09-25 10:04:43 [http-nio-8080-exec-2] 调试 o.s.w.s.m.a.ResponseStatusExceptionResolver -解决处理程序异常 [org.springframework.web.servlet.mvc.ParameterizableViewController@c85e70]:org.springframework.web.HttpRequestMethodNotSupportedException:不支持请求方法POST"2016-09-25 10:04:43 [http-nio-8080-exec-2] 调试 o.s.w.s.m.s.DefaultHandlerExceptionResolver -解决处理程序异常 [org.springframework.web.servlet.mvc.ParameterizableViewController@c85e70]:org.springframework.web.HttpRequestMethodNotSupportedException:不支持请求方法POST"2016-09-25 10:04:43 [http-nio-8080-exec-2] 警告 o.s.web.servlet.PageNotFound -不支持请求方法POST"2016-09-25 10:04:43 [http-nio-8080-exec-2] 调试 o.s.s.w.h.writers.HstsHeaderWriter -不注入 HSTS 标头,因为它与 requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@16580a4 不匹配2016-09-25 10:04:43 [http-nio-8080-exec-2] 调试 os.web.servlet.DispatcherServlet -Null ModelAndView 返回给 DispatcherServlet,名称为dispatcherServlet":假设 HandlerAdapter 已完成请求处理2016-09-25 10:04:43 [http-nio-8080-exec-2] 调试 os.web.servlet.DispatcherServlet -成功完成请求

另外,关于这个问题还有另一个问题没有提供答案使用 oauth2 和 formlogin 未在 Spring Security 中调用 usernamepasswordauthenticationfilter

解决方案

这是我的 ResourceServer 配置错误的问题.

使用以下配置,一切正常:

@Configuration@EnableResourceServer受保护的静态类 ResourceServerConfiguration 扩展了 ResourceServerConfigurerAdapter {@自动连线私有 ResourceServerTokenServices 令牌服务;@覆盖公共无效配置(ResourceServerSecurityConfigurer 资源){//@格式化程序:关闭资源.resourceId(RESOURCE_ID).tokenServices(tokenService);//@格式化程序:打开}@覆盖公共无效配置(HttpSecurity http)抛出异常{//@格式化程序:关闭http.antMatcher("/api/**" ).authorizeRequests().anyRequest().authenticated().and().csrf().disable().sessionManagement().sessionCreationPolicy(STATELESS);//@格式化程序:打开}}

In my Spring Boot application I'm trying to configure OAuth2 implicit flow. For this purpose I'm trying to configure custom login form.

This is my config:

@Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("index"); registry.addViewController("/login").setViewName("login"); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); } } @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private SocialAuthenticationSuccessHandler socialAuthenticationSuccessHandler; @Autowired private DBUserDetailsService userDetailsService; @Value("${social.postLogin.url}") private String postLoginUrl; @Override public void configure(WebSecurity web) throws Exception { // Spring Security ignores request to static resources such as CSS or JS // files. web.ignoring().antMatchers("/static/**"); } @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off http.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class); // Set a custom successHandler on the SocialAuthenticationFilter final SpringSocialConfigurer socialConfigurer = new SpringSocialConfigurer(); socialConfigurer.addObjectPostProcessor(new ObjectPostProcessor<SocialAuthenticationFilter>() { @Override public <O extends SocialAuthenticationFilter> O postProcess(O socialAuthenticationFilter) { socialAuthenticationFilter.setAuthenticationSuccessHandler(socialAuthenticationSuccessHandler); socialAuthenticationFilter.setPostLoginUrl(postLoginUrl); return socialAuthenticationFilter; } }); http .csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers("/oauth/authorize").authenticated() //Anyone can access the urls .antMatchers("/auth/**").permitAll() .antMatchers("/actuator/health").permitAll() .antMatchers("/actuator/**").hasAuthority("PERMISSION_READ_ACTUATOR_DATA") .antMatchers("/login").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .loginProcessingUrl("/login") .usernameParameter("username") .passwordParameter("password") .permitAll() //Adds the SocialAuthenticationFilter to Spring Security's filter chain. .and() // apply the configuration from the socialConfigurer (adds the SocialAuthenticationFilter) .apply(socialConfigurer); // @formatter:on } /** * Configures the authentication manager bean which processes authentication * requests. */ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder()); } @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } } @Configuration public class OAuth2ServerConfig { private static final String RESOURCE_ID = "restservice"; @Autowired private DBUserDetailsService userDetailsService; @Bean @Primary public DefaultTokenServices tokenServices() { DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); defaultTokenServices.setTokenStore(tokenStore()); defaultTokenServices.setSupportRefreshToken(true); return defaultTokenServices; } @Bean public JwtAccessTokenConverter accessTokenConverter() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter() { @Override public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { DBUserDetails user = (DBUserDetails) authentication.getUserAuthentication().getPrincipal(); final Map<String, Object> additionalInfo = new HashMap<>(); additionalInfo.put("user_id", user.getUser().getId()); ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo); OAuth2AccessToken enhancedToken = super.enhance(accessToken, authentication); return enhancedToken; } }; converter.setSigningKey("123"); DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter(); DefaultUserAuthenticationConverter userTokenConverter = new DefaultUserAuthenticationConverter(); userTokenConverter.setUserDetailsService(userDetailsService); accessTokenConverter.setUserTokenConverter(userTokenConverter); converter.setAccessTokenConverter(accessTokenConverter); return converter; } @Bean public TokenStore tokenStore() { return new JwtTokenStore(accessTokenConverter()); } @Configuration @EnableAuthorizationServer protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { @Autowired @Qualifier("authenticationManagerBean") private AuthenticationManager authenticationManager; @Autowired private TokenStore tokenStore; @Autowired private TokenEnhancer tokenEnhancer; @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { // @formatter:off endpoints .tokenStore(tokenStore) .tokenEnhancer(tokenEnhancer) .authenticationManager(this.authenticationManager); // @formatter:on } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // @formatter:off clients .inMemory() .withClient("clientapp") .authorizedGrantTypes("password","refresh_token") //.authorizedGrantTypes("implicit") .authorities("ROLE_CLIENT") .scopes("read", "write") .resourceIds(RESOURCE_ID) .secret("123456") .and() .withClient("clientapp1") .authorizedGrantTypes("implicit") .scopes("read", "write") .autoApprove(true); // @formatter:on } } @Configuration @EnableResourceServer protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { @Autowired private ResourceServerTokenServices tokenService; @Override public void configure(ResourceServerSecurityConfigurer resources) { // @formatter:off resources .resourceId(RESOURCE_ID) .tokenServices(tokenService); // @formatter:on } @Override public void configure(HttpSecurity http) throws Exception { // @formatter:off http .authorizeRequests() .antMatchers("/profile/*").authenticated() .and().csrf() .disable().sessionManagement().sessionCreationPolicy(STATELESS); // @formatter:on } } }

login.html page Thymeleaf template:

<!DOCTYPE html> <html xmlns="www.w3/1999/xhtml" xmlns:th="www.thymeleaf" xmlns:sec="www.thymeleaf/thymeleaf-extras-springsecurity3"> <head> <title>Spring Security Example </title> </head> <body> <div th:if="${param.error}"> Invalid username and password. </div> <div th:if="${param.logout}"> You have been logged out. </div> <form th:action="@{/login}" method="post"> <div><label> User Name : <input type="text" name="username"/> </label></div> <div><label> Password: <input type="password" name="password"/> </label></div> <div><input type="submit" value="Sign In"/></div> </form> </body> </html>

Maven artifact versions:

<spring.boot.version>1.4.0.RELEASE</spring.boot.version> <spring-security-core.version>4.1.3.RELEASE</spring-security-core.version> <spring-security-oauth2.version>2.0.11.RELEASE</spring-security-oauth2.version>

Right now, when I'm trying to access following url:

localhost:8080/oauth/authorize?response_type=implicit&client_id=clientapp1

I'm successfully redirected to my login page at localhost:8080/login but when I enter username/password and press "Sign in" button I'm getting following error:

Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback. Sat Sep 24 21:19:44 EEST 2016 There was an unexpected error (type=Method Not Allowed, status=405). Request method 'POST' not supported

What am I doing wrong and how to fix this issue ?

UPDATED

In debug I can see the following output:

DispatcherServlet with name 'dispatcherServlet' processing POST request for [/login] 2016-09-25 10:04:43 [http-nio-8080-exec-2] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Looking up handler method for path /login 2016-09-25 10:04:43 [http-nio-8080-exec-2] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Did not find handler method for [/login] 2016-09-25 10:04:43 [http-nio-8080-exec-2] DEBUG o.s.w.s.h.SimpleUrlHandlerMapping - Mapping [/login] to HandlerExecutionChain with handler [org.springframework.web.servlet.mvc.ParameterizableViewController@c85e70] and 1 interceptor 2016-09-25 10:04:43 [http-nio-8080-exec-2] DEBUG o.s.w.s.m.a.ResponseStatusExceptionResolver - Resolving exception from handler [org.springframework.web.servlet.mvc.ParameterizableViewController@c85e70]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported 2016-09-25 10:04:43 [http-nio-8080-exec-2] DEBUG o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolving exception from handler [org.springframework.web.servlet.mvc.ParameterizableViewController@c85e70]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported 2016-09-25 10:04:43 [http-nio-8080-exec-2] WARN o.s.web.servlet.PageNotFound - Request method 'POST' not supported 2016-09-25 10:04:43 [http-nio-8080-exec-2] DEBUG o.s.s.w.h.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@16580a4 2016-09-25 10:04:43 [http-nio-8080-exec-2] DEBUG o.s.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling 2016-09-25 10:04:43 [http-nio-8080-exec-2] DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request

Also, there is another question about this issue with no answer provided usernamepasswordauthenticationfilter not getting invoked in spring security with oauth2 and formlogin

解决方案

It was my issue with a wrong configuration of ResourceServer.

With a following configuration everything is working fine:

@Configuration @EnableResourceServer protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { @Autowired private ResourceServerTokenServices tokenService; @Override public void configure(ResourceServerSecurityConfigurer resources) { // @formatter:off resources .resourceId(RESOURCE_ID) .tokenServices(tokenService); // @formatter:on } @Override public void configure(HttpSecurity http) throws Exception { // @formatter:off http .antMatcher("/api/**" ) .authorizeRequests().anyRequest().authenticated() .and() .csrf().disable() .sessionManagement().sessionCreationPolicy(STATELESS); // @formatter:on } }

更多推荐

Spring Boot OAuth2 隐式流 + 表单登录和请求方法“POST"不支持错误

本文发布于:2023-10-29 10:05:05,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1539412.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:不支持   表单   错误   方法   隐式

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!