我使用弹簧靴和弹簧安全。
在我的休息控制器中,我有一个方法
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled=true)
@EnableWebSecurity
public class ApplicationSecurity extends WebSecurityConfigurerAdapter {
@Autowired
private RESTAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private RESTAuthenticationFailureHandler authenticationFailureHandler;
@Autowired
private RESTAuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
private UserDetailsService userDetailsService;
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(encoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/rest/**").authenticated();
http.csrf().disable();
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
http.formLogin().successHandler(authenticationSuccessHandler);
http.formLogin().failureHandler(authenticationFailureHandler);
http.logout().logoutUrl("/logout");
http.logout().logoutSuccessUrl("/");
// CSRF tokens handling
//http.addFilterAfter(new CsrfTokenResponseHeaderBindingFilter(), CsrfFilter.class);
}
}
@RequestMapping(value = "/rest")
@RestController
public class MemberController {
@GetMapping(value = "/members/card")
public boolean hasCardIdValid(@RequestBody String cardId) {
return memberService.hasCardIdValid(cardId);
}
}
在另一个春季启动应用程序中,我尝试调用hasCreditCard方法
@Autowired
public GlobalScan(RestTemplateBuilder restTemplateBuilder, @Value("${main.server.url}") String mainServerUrl, @Value("${commerce.username}") String commerceUsername, @Value("${commerce.password}")String commercePassword) {
this.restTemplate = restTemplateBuilder.basicAuthorization(commerceUsername, commercePassword).rootUri(mainServerUrl).build();
}
I do a call with this code
Map<String, String> vars = new HashMap<String, String>();
vars.put("cardId", cardId);
boolean accessAllowed = restTemplate.getForObject("/rest/members/card/" , Boolean.class, vars);
我收到此消息
2016-11-02 16:20:50.601 DEBUG 7139 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/rest/members/card/'; against '/login'
2016-11-02 16:20:50.601 DEBUG 7139 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/rest/members/card/'; against '/rest/**'
2016-11-02 16:20:50.601 DEBUG 7139 --- [nio-8080-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /rest/members/card/; Attributes: [authenticated]
2016-11-02 16:20:50.601 DEBUG 7139 --- [nio-8080-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055e4a6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
2016-11-02 16:20:50.602 DEBUG 7139 --- [nio-8080-exec-1] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@3d300693, returned: -1
2016-11-02 16:20:50.602 TRACE 7139 --- [nio-8080-exec-1] ationConfigEmbeddedWebApplicationContext : Publishing event in org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@2bdd8394: org.springframework.security.access.event.AuthorizationFailureEvent[source=FilterInvocation: URL: /rest/members/card/]
2016-11-02 16:20:50.606 DEBUG 7139 --- [nio-8080-exec-1] o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-4.1.1.RELEASE.jar:4.1.1.RELEASE]
在我的主应用程序中,我使用表单登录连接到应用程序,就像您在spring安全配置中看到的那样。
从我的其他应用程序如何在没有表单登录的情况下调用ws?
试图用这个
来调用ws final RequestConfig config = RequestConfig.custom().setConnectTimeout(timeout * 1000).setConnectionRequestTimeout(timeout * 1000).setSocketTimeout(timeout * 1000).build();
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope("http://localhost", 8080, AuthScope.ANY_REALM), new UsernamePasswordCredentials("bob", "smith"));
final CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).setDefaultCredentialsProvider(credentialsProvider).build();
final ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(client);
RestTemplate restTemplate = new RestTemplate(requestFactory);
ResponseEntity<MemberDto> member = restTemplate.getForEntity("http://localhost:8080/rest/members/1", MemberDto.class);
答案 0 :(得分:1)
spring security中的默认密码由以下属性配置:security.user.password=YOUR_PASSWORD
这应该在您的主应用程序中完成,您可以在其中进行安全配置并尝试呼叫。
您可以通过提供security.user.password来更改密码。 这个和其他有用的属性通过外部化 SecurityProperties(属性前缀“security”)。
所以,如果你没有更新属性以匹配commerce.password
中的密码,spring将拒绝你的授权,你将获得401.默认情况下,它会使用一些随机生成的密码,它会在启动时打印到控制台。 documentation
答案 1 :(得分:1)
您正在配置formLogin()
,但您尝试在RestTemplate中使用http Basic Auth。
对于通过http REST的请求,我建议您更改配置以使用基本身份验证:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/rest/**").authenticated();
http.csrf().disable();
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
http.httpBasic();
http.logout().logoutUrl("/logout");
http.logout().logoutSuccessUrl("/");
// CSRF tokens handling
//http.addFilterAfter(new CsrfTokenResponseHeaderBindingFilter(), CsrfFilter.class);
}
如果您需要两者,我认为您可以配置两者。
答案 2 :(得分:0)
将BASIC身份验证添加到现有配置
@Override
protected void configure(HttpSecurity http) throws Exception {
http
....
.and()
.formLogin() // <------ Keep this
....
.and()
.httpBasic() // <------ Add BASIC Auth
.and()
.....;
}
使用RestTemplate编写一个简单的客户端
public static void main(String[] args) {
RestTemplate rest = new RestTemplate(new ArrayList(Arrays.asList(new MappingJackson2HttpMessageConverter())));
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Basic YOUR_BASE64_ENCODED_CREDENTIALS");
MediaType applicationJson = new MediaType("application","json");
headers.setContentType(applicationJson);
headers.setAccept(Collections.singletonList(applicationJson));
ResponseEntity<YourResponseObject> resp = rest.exchange("http://URL/rest/yourendpoint", HttpMethod.GET, new HttpEntity<String>("parameters", headers), YourResponseObject.class);
System.out.println(resp.getBody());
}
YOUR_BASE64_ENCODED_CREDENTIALS =&gt;如果使用Java 8,您可以使用java.util.Base64
,否则使用commons-codec来执行此操作或其他操作。
<强>更新强> Spring引用引用:http://docs.spring.io/spring-security/site/docs/current/reference/html/jc.html#jc-httpsecurity