我创建了一个简单的授权服务器,但无法配置它。
- 启动这两个应用(8080 用于身份验证服务器,9999 用于客户端(。
- 转到
localhost:9999/client
并重定向到localhost:8080/login
(如预期的那样(。 - 使用用户/用户填写登录表单。
- 重定向到
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
更新:
当一切正常时,我下载了一个教程,但它具有仅用于 OAuth2 身份验证的 ssoFilter。我只想用loginForm
配置它.
我还在 GitHub 上分享了一个临时示例。我认为查找它的问题会更容易。
有不同的端口 99998080 当它从与第一个资源本身所服务的域或端口不同的域或端口请求资源时,这将导致跨源 HTTP 请求。
有关 HTTP 访问控制 (CORS( 的更多详细信息
在官方春季网站上有一个泥炭很好的例子 为 RESTful Web 服务启用跨源请求
我建议只需通过实现过滤器接口即可在您的应用程序上进行 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 启动应用程序,请确保包括在组件扫描中创建新过滤器的包。
如果使用"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>
用户详细信息由 org.springframework.cloud.security.oauth2.resource.UserInfoTokenServices
加载,因此值得在其中添加一个断点以查看它从/me 端点获取的内容。
此类仅提取基本的用户详细信息,实际上查看代码似乎设置了硬编码的ROLE_USER角色,因此建议您创建自己的实现,以便为用户正确设置OAuth2Authentication
。
更改了一下您的代码,它在本地对我有用。
@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。
因为您的身份验证服务器和客户端都是从同一个主机(localhost
(提供的,所以您的 Web 浏览器可能会混淆哪个 http 端点属于哪个 http cookie。
尝试将一个指定为 127.0.0.1
,另一个指定为 localhost
,以便您的浏览器将 http cookie 关联到其正确的端点。