spring security oauth2授权服务器自定义redirectUri匹配规则

在spring security中授权服务器的默认匹配规则是全路径匹配
详见源码 AuthorizationEndpoint.authorize
redirectResolver.resolveRedirect(redirectUriParameter, client);

@RequestMapping(value = "/oauth/authorize")
	public ModelAndView authorize(Map<String, Object> model, @RequestParam Map<String, String> parameters,
			//...省略

			// The resolved redirect URI is either the redirect_uri from the parameters or the one from
			// clientDetails. Either way we need to store it on the AuthorizationRequest.
			String redirectUriParameter = authorizationRequest.getRequestParameters().get(OAuth2Utils.REDIRECT_URI);
			String resolvedRedirect = redirectResolver.resolveRedirect(redirectUriParameter, client);
			if (!StringUtils.hasText(resolvedRedirect)) {
				throw new RedirectMismatchException(
						"A redirectUri must be either supplied or preconfigured in the ClientDetails");
			}
			authorizationRequest.setRedirectUri(resolvedRedirect);
//...省略
	}

默认匹配解析器 DefaultRedirectResolver

protected boolean redirectMatches(String requestedRedirect, String redirectUri) {
		UriComponents requestedRedirectUri = UriComponentsBuilder.fromUriString(requestedRedirect).build();
		String requestedRedirectUriScheme = (requestedRedirectUri.getScheme() != null ? requestedRedirectUri.getScheme() : "");
		String requestedRedirectUriHost = (requestedRedirectUri.getHost() != null ? requestedRedirectUri.getHost() : "");
		String requestedRedirectUriPath = (requestedRedirectUri.getPath() != null ? requestedRedirectUri.getPath() : "");

		UriComponents registeredRedirectUri = UriComponentsBuilder.fromUriString(redirectUri).build();
		String registeredRedirectUriScheme = (registeredRedirectUri.getScheme() != null ? registeredRedirectUri.getScheme() : "");
		String registeredRedirectUriHost = (registeredRedirectUri.getHost() != null ? registeredRedirectUri.getHost() : "");
		String registeredRedirectUriPath = (registeredRedirectUri.getPath() != null ? registeredRedirectUri.getPath() : "");

		boolean portsMatch = this.matchPorts ? (registeredRedirectUri.getPort() == requestedRedirectUri.getPort()) : true;

		return registeredRedirectUriScheme.equals(requestedRedirectUriScheme) &&
				hostMatches(registeredRedirectUriHost, requestedRedirectUriHost) &&
				portsMatch &&
				// Ensure exact path matching
				registeredRedirectUriPath.equals(StringUtils.cleanPath(requestedRedirectUriPath));
	}

从最后registeredRedirectUriPath.equals(StringUtils.cleanPath(requestedRedirectUriPath));这句看出来默认的规则就是全路径匹配。
我们如果需要自定义就直接写个类实现RedirectResolver接口 直接copy这个类 定义一个 antMatcher然后替换这个判断就好了
修改如下:

 protected boolean redirectMatches(String requestedRedirect, String redirectUri) {
        UriComponents requestedRedirectUri = UriComponentsBuilder.fromUriString(requestedRedirect).build();
        String requestedRedirectUriScheme = (requestedRedirectUri.getScheme() != null ? requestedRedirectUri.getScheme() : "");
        String requestedRedirectUriHost = (requestedRedirectUri.getHost() != null ? requestedRedirectUri.getHost() : "");
        String requestedRedirectUriPath = (requestedRedirectUri.getPath() != null ? requestedRedirectUri.getPath() : "");
        
        UriComponents registeredRedirectUri = UriComponentsBuilder.fromUriString(redirectUri).build();
        String registeredRedirectUriScheme = (registeredRedirectUri.getScheme() != null ? registeredRedirectUri.getScheme() : "");
        String registeredRedirectUriHost = (registeredRedirectUri.getHost() != null ? registeredRedirectUri.getHost() : "");
        String registeredRedirectUriPath = (registeredRedirectUri.getPath() != null ? registeredRedirectUri.getPath() : "");
        
        boolean portsMatch = this.matchPorts ? (registeredRedirectUri.getPort() == requestedRedirectUri.getPort()) : true;
        
        return registeredRedirectUriScheme.equals(requestedRedirectUriScheme) &&
            hostMatches(registeredRedirectUriHost, requestedRedirectUriHost) &&
            portsMatch &&
            // Ensure exact path matching
            pathMatcher(registeredRedirectUriPath,StringUtils.cleanPath(requestedRedirectUriPath));
    }
    
    private boolean pathMatcher(String requestPath,String registeredPath){
        AntPathMatcher antPathMatcher = new AntPathMatcher();
        return antPathMatcher.matchStart(registeredPath, requestPath);
    }

这样即可与github 等站点的匹配规则一致

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
自定义Spring Security OAuth2密码模式的登录路径,你可以使用以下步骤: 1. 创建自定义登录页面和控制器,例如/login/custom。 2. 在Spring Security配置类中,使用formLogin()方法启用表单登录,并使用loginPage()方法指定登录页面的路径和permitAll()方法允许所有用户访问登录页面。 ``` @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login/custom") .permitAll() .and() .oauth2Login() .and() .oauth2Client(); } } ``` 3. 在控制器中,编写处理登录请求的方法,并使用AuthenticationManager.authenticate()方法进行身份验证。如果身份验证成功,重定向到请求的资源,否则返回登录页面。 ``` @Controller public class LoginController { @Autowired private AuthenticationManager authenticationManager; @GetMapping("/login/custom") public String showLoginForm() { return "login"; } @PostMapping("/login/custom") public String submitLoginForm(@RequestParam String username, @RequestParam String password, HttpServletRequest request, HttpServletResponse response) { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password); try { Authentication authentication = authenticationManager.authenticate(token); SecurityContextHolder.getContext().setAuthentication(authentication); return "redirect:" + request.getParameter("redirect_uri"); } catch (AuthenticationException e) { return "login"; } } } ``` 4. 在OAuth2客户端配置中,使用loginPage()方法指定登录页面的路径。 ``` @Configuration @EnableOAuth2Client public class OAuth2ClientConfig { @Value("${security.oauth2.client.client-id}") private String clientId; @Value("${security.oauth2.client.client-secret}") private String clientSecret; @Value("${security.oauth2.client.access-token-uri}") private String accessTokenUri; @Value("${security.oauth2.client.user-authorization-uri}") private String userAuthorizationUri; @Value("${security.oauth2.client.redirect-uri}") private String redirectUri; @Value("${security.oauth2.client.scope}") private String scope; @Bean public OAuth2ProtectedResourceDetails oauth2ProtectedResourceDetails() { ClientCredentialsResourceDetails details = new ClientCredentialsResourceDetails(); details.setClientId(clientId); details.setClientSecret(clientSecret); details.setAccessTokenUri(accessTokenUri); details.setScope(Arrays.asList(scope.split(","))); return details; } @Bean public OAuth2RestTemplate oauth2RestTemplate() { OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(oauth2ProtectedResourceDetails()); restTemplate.setMessageConverters(Arrays.asList(new MappingJackson2HttpMessageConverter())); return restTemplate; } @Bean public OAuth2ClientContext oauth2ClientContext() { return new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest()); } @Bean public AuthorizationCodeResourceDetails authorizationCodeResourceDetails() { AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails(); details.setClientId(clientId); details.setClientSecret(clientSecret); details.setAccessTokenUri(accessTokenUri); details.setUserAuthorizationUri(userAuthorizationUri); details.setScope(Arrays.asList(scope.split(","))); details.setUseCurrentUri(false); details.setPreEstablishedRedirectUri(redirectUri); details.setAuthenticationScheme(AuthenticationScheme.query); return details; } @Bean public OAuth2RestOperations oauth2RestOperations() { return new OAuth2RestTemplate(authorizationCodeResourceDetails(), oauth2ClientContext()); } @Bean public OAuth2ClientAuthenticationProcessingFilter oauth2ClientAuthenticationProcessingFilter() { OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter("/login/custom"); OAuth2RestTemplate restTemplate = oauth2RestTemplate(); restTemplate.setAccessTokenProvider(new AuthorizationCodeAccessTokenProvider()); filter.setRestTemplate(restTemplate); UserInfoTokenServices tokenServices = new UserInfoTokenServices(userInfoUri(), clientId); tokenServices.setRestTemplate(restTemplate); filter.setTokenServices(tokenServices); return filter; } @Bean public FilterRegistrationBean oauth2ClientFilterRegistration(OAuth2ClientAuthenticationProcessingFilter filter) { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(filter); registration.setOrder(-100); return registration; } @Value("${security.oauth2.client.user-info-uri}") private String userInfoUri; @Bean public String userInfoUri() { return userInfoUri; } } ``` 这些步骤可以帮助你自定义Spring Security OAuth2密码模式的登录路径。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值