如何禁用弹簧安全的特定网址

我正在使用无状态弹簧安全,但是如果注册,我想禁用弹簧安全

antMatchers("/api/v1/signup").permitAll().

但它不工作,我得到下面的错误:

 message=An Authentication object was not found in the SecurityContext, type=org.springframework.security.authentication.AuthenticationCredentialsNotFoundException

我认为这意味着春季安全过滤器正在工作

我的 url 顺序永远是“/api/v1”

我的弹簧配置是

@Override
protected void configure(HttpSecurity http) throws Exception {


http.
csrf().disable().
sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).
and().
authorizeRequests().
antMatchers("/api/v1/signup").permitAll().
anyRequest().authenticated().
and().
anonymous().disable();
http.addFilterBefore(new AuthenticationFilter(authenticationManager()), BasicAuthenticationFilter.class);
}

我的认证过滤器是

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = asHttp(request);
HttpServletResponse httpResponse = asHttp(response);


String username = httpRequest.getHeader("X-Auth-Username");
String password = httpRequest.getHeader("X-Auth-Password");
String token = httpRequest.getHeader("X-Auth-Token");


String resourcePath = new UrlPathHelper().getPathWithinApplication(httpRequest);


try {


if (postToAuthenticate(httpRequest, resourcePath)) {
processUsernamePasswordAuthentication(httpResponse, username, password);
return;
}


if(token != null){
processTokenAuthentication(token);
}
chain.doFilter(request, response);
} catch (InternalAuthenticationServiceException internalAuthenticationServiceException) {
SecurityContextHolder.clearContext();
logger.error("Internal authentication service exception", internalAuthenticationServiceException);
httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (AuthenticationException authenticationException) {
SecurityContextHolder.clearContext();
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authenticationException.getMessage());
} finally {
}
}


private HttpServletRequest asHttp(ServletRequest request) {
return (HttpServletRequest) request;
}


private HttpServletResponse asHttp(ServletResponse response) {
return (HttpServletResponse) response;
}


private boolean postToAuthenticate(HttpServletRequest httpRequest, String resourcePath) {
return Constant.AUTHENTICATE_URL.equalsIgnoreCase(resourcePath) && httpRequest.getMethod().equals("POST");
}


private void processUsernamePasswordAuthentication(HttpServletResponse httpResponse,String username, String password) throws IOException {
Authentication resultOfAuthentication = tryToAuthenticateWithUsernameAndPassword(username, password);
SecurityContextHolder.getContext().setAuthentication(resultOfAuthentication);
httpResponse.setStatus(HttpServletResponse.SC_OK);
httpResponse.addHeader("Content-Type", "application/json");
httpResponse.addHeader("X-Auth-Token", resultOfAuthentication.getDetails().toString());
}


private Authentication tryToAuthenticateWithUsernameAndPassword(String username,String password) {
UsernamePasswordAuthenticationToken requestAuthentication = new UsernamePasswordAuthenticationToken(username, password);
return tryToAuthenticate(requestAuthentication);
}


private void processTokenAuthentication(String token) {
Authentication resultOfAuthentication = tryToAuthenticateWithToken(token);
SecurityContextHolder.getContext().setAuthentication(resultOfAuthentication);
}


private Authentication tryToAuthenticateWithToken(String token) {
PreAuthenticatedAuthenticationToken requestAuthentication = new PreAuthenticatedAuthenticationToken(token, null);
return tryToAuthenticate(requestAuthentication);
}


private Authentication tryToAuthenticate(Authentication requestAuthentication) {
Authentication responseAuthentication = authenticationManager.authenticate(requestAuthentication);
if (responseAuthentication == null || !responseAuthentication.isAuthenticated()) {
throw new InternalAuthenticationServiceException("Unable to authenticate Domain User for provided credentials");
}
logger.debug("User successfully authenticated");
return responseAuthentication;
}

我的控制器是

@RestController
public class UserController {


@Autowired
UserService userService;


/**
* to pass user info to service
*/
@RequestMapping(value = "api/v1/signup",method = RequestMethod.POST)
public String saveUser(@RequestBody User user) {
userService.saveUser(user);
return "User registerted successfully";
}
}

我对春天完全陌生,请帮助我如何做到这一点?

205267 次浏览
<http pattern="/resources/**" security="none"/>

Or with Java configuration:

web.ignoring().antMatchers("/resources/**");

Instead of the old:

 <intercept-url pattern="/resources/**" filters="none"/>

for exp . disable security for a login page :

  <intercept-url pattern="/login*" filters="none" />

When using permitAll it means every authenticated user, however you disabled anonymous access so that won't work.

What you want is to ignore certain URLs for this override the configure method that takes WebSecurity object and ignore the pattern.

@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api/v1/signup");
}

And remove that line from the HttpSecurity part. This will tell Spring Security to ignore this URL and don't apply any filters to them.

I have a better way:

http
.authorizeRequests()
.antMatchers("/api/v1/signup/**").permitAll()
.anyRequest().authenticated()

This may be not the full answer to your question, however if you are looking for way to disable csrf protection you can do:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/web/admin/**").hasAnyRole(ADMIN.toString(), GUEST.toString())
.anyRequest().permitAll()
.and()
.formLogin().loginPage("/web/login").permitAll()
.and()
.csrf().ignoringAntMatchers("/contact-email")
.and()
.logout().logoutUrl("/web/logout").logoutSuccessUrl("/web/").permitAll();
}


@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin").password("admin").roles(ADMIN.toString())
.and()
.withUser("guest").password("guest").roles(GUEST.toString());
}


}

I have included full configuration but the key line is:

.csrf().ignoringAntMatchers("/contact-email")

As @M.Deinum already wrote the answer.

I tried with api /api/v1/signup. it will bypass the filter/custom filter but an additional request invoked by the browser for /favicon.ico, so, I add this also in web.ignoring() and it works for me.

@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api/v1/signup", "/favicon.ico");
}

Maybe this is not required for the above question.

If you want to ignore multiple API endpoints you can use as follow:

 @Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable().authorizeRequests()
.antMatchers("/api/v1/**").authenticated()
.antMatchers("api/v1/authenticate**").permitAll()
.antMatchers("**").permitAll()
.and().exceptionHandling().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}

I faced the same problem here's the solution:(Explained)

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(HttpMethod.POST,"/form").hasRole("ADMIN")  // Specific api method request based on role.
.antMatchers("/home","/basic").permitAll()  // permited urls to guest users(without login).
.anyRequest().authenticated()
.and()
.formLogin()       // not specified form page to use default login page of spring security.
.permitAll()
.and()
.logout().deleteCookies("JSESSIONID")  // delete memory of browser after logout.


.and()
.rememberMe().key("uniqueAndSecret"); // remember me check box enabled.


http.csrf().disable();  **// ADD THIS CODE TO DISABLE CSRF IN PROJECT.**
}