我正在使用spring boot 1.5.6和OAuth2和JWT的安全性
~/repos/jtor > mvn dependency:tree | grep security [INFO] +- org.springframework.security.oauth:spring-security-oauth2:jar:2.0.14.RELEASE:compile [INFO] | +- org.springframework.security:spring-security-core:jar:4.2.3.RELEASE:compile [INFO] | +- org.springframework.security:spring-security-config:jar:4.2.3.RELEASE:compile [INFO] | +- org.springframework.security:spring-security-web:jar:4.2.3.RELEASE:compile [INFO] +- org.springframework.security:spring-security-jwt:jar:1.0.8.RELEASE:compile [INFO] \- org.springframework.security:spring-security-test:jar:4.2.3.RELEASE:test
通过以下配置,对/
和/api/person
的请求将生成标准OAuth 401:
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
我想要的是要求/api/**
获取401,而任何其他请求(如/
或/welcome
)被重定向(302)到我的授权服务器(Ping Federate)。登录后,我将被重定向回来,我的GET到/
将返回我的HTML(或其他)。
换句话说,对API的调用需要一个令牌,而非api调用将遵循oauth2代码流。
我的配置:
security:
basic:
enabled: false
oauth2:
client:
accessTokenUri: https://ping-dev.my-comp.com:9031/as/token.oauth2
userAuthorizationUri: https://ping-dev.my-comp.com:9031/as/authorization.oauth2
logoutUri: https://ping-dev.my-comp.com:9031/ext/logout
clientId: oauth2
clientSecret: foo
authentication-scheme: header
resource:
jwt:
keyValue: |
-----BEGIN PUBLIC KEY-----
MY KEY HERE
-----END PUBLIC KEY-----
我的应用程序
@SpringBootApplication
@Slf4j
public class JtorApplication {
public static void main(String[] args) {
SpringApplication.run(JtorApplication.class, args);
}
@Configuration
@EnableResourceServer
protected static class ResourceServer extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests()
.antMatchers("/info", "/health", "/public/**").permitAll()
.anyRequest().fullyAuthenticated();
// @formatter:on
}
}
/*
this class allows me to access public resources with a URL that starts with "public/", which
allows me to bypass security on any public resource in a clean way.
*/
@Configuration
protected static class WebMvcConfigurer extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/public/**").addResourceLocations("classpath:/public/");
}
}
/*
This is the API I want protected via Oauth2/JWT.
Only calls containing a valid Bearer token should be allowed.
Calls without a token should get back a standard Oauth 401 error
*/
@RestController
@RequestMapping("/api")
protected static class ApiController {
@GetMapping("/person")
public Person getPerson() {
return Person.builder().id(1).name("Jason").build();
}
@Getter
@Builder
static class Person {
private int id;
private String name;
}
}
/*
This is the "web app" controller that returns an "app", which will make ajax calls to the api.
I want this route to be secured, but instead of just returning a 401, I want to start the
OAuth login process by sending the user to my OAuth Server
*/
@Controller
protected static class WebAppController {
@RequestMapping("/")
public String webapp() {
return "index";
}
// this should bypass security because it starts with "public"
@RequestMapping("/public")
public String publicPage() {
return "public";
}
}
}
如果要使用不同的身份验证机制处理应用程序的不同部分,可以创建扩展WebSecurityConfigurerAdapter
的其他配置类,并在那里指定安全性约束。
在调用.authorizeRequests()
之前,请确保在AntMatcher中指定应将安全配置应用于的URL。见下面的代码。
您可以使用@Order
注释设置安全配置的顺序。
HTTP基本身份验证示例
@Configuration
@Order(2) //will be applied after @Order(1), etc...
protected AnotherSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**") //apply only to api endpoints
.authorizeRequests()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.and()
.httpBasic(); //set to basic auth
}
}
试试这个:
protected void configure(HttpSecurity http) throws Exception {
http
....
.and()
.exceptionHandling().authenticationEntryPoint(entryPoint())
....
}
private AuthenticationEntryPoint entryPoint() {
return new AuthenticationEntryPoint() {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
//your code here - can key off of the request
}
};
}