So deaktivieren Sie die Federsicherheit für eine bestimmte URL


84

Ich verwende die zustandslose Federsicherheit, aber im Falle einer Anmeldung möchte ich die Federsicherheit deaktivieren. Ich habe die Verwendung deaktiviert

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

aber es funktioniert nicht, ich erhalte folgende Fehlermeldung:

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

Ich denke, dies bedeutet, dass Federsicherheitsfilter funktionieren

Die Bestellung meiner URL lautet immer "/ api / v1".

Meine Frühlingskonfiguration ist

@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);
    }

Mein Authentifizierungsfilter ist

@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;
        }

Mein Controller ist

@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";
    }
}

Ich bin völlig neu im Frühling, bitte helfen Sie mir, wie es geht?


Antworten:


156

Wenn Sie permitAlles verwenden, bedeutet dies, dass jeder authentifizierte Benutzer den anonymen Zugriff deaktiviert hat, sodass dies nicht funktioniert.

Sie möchten bestimmte URLs ignorieren, um die configureMethode zu überschreiben, mit der das WebSecurityObjekt und ignoredas Muster verwendet werden.

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

Und entfernen Sie diese Linie vom HttpSecurityTeil. Dadurch wird Spring Security angewiesen, diese URL zu ignorieren und keine Filter auf sie anzuwenden.


4
In welche Datei wird das geschrieben?
Jacob Zimmerman

3
@ JacobZimmerman spring.io/blog/2013/07/03/… der Konfigurator für Web-Sicherheitsklasse
Askar Ibragimov

1
Ich möchte nur hinzufügen, dass Sie erweitern müssen WebSecurityConfigurerAdapterund overridedies methoddarin.
muasif80

19

Ich habe einen besseren Weg:

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

3
Wo soll dieses Snippet heißen?
Viacheslav Shalamov

@ViacheslavShalamov In Ihrem WebSecurityConfig extends WebSecurityConfigurerAdapter‚s - configure(HttpSecurity http)Methode. Siehe baeldung.com/java-config-spring-security
jAC

1
Dies ist am häufigsten im Internet, eigentlich ist es eine falsche Praxis. Wenn Sie alles zulassen, müssen Sie sich noch authentifizieren, aber Sie erlauben es schließlich. Warum sollten wir also eine Authentifizierung (ich meine, Authentifizierungsfilter werden weiterhin ausgelöst) für einen Anmeldezugriff durchführen?
Chao

13
<http pattern="/resources/**" security="none"/>

Oder mit Java-Konfiguration:

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

Anstelle des alten:

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

für exp. Deaktivieren Sie die Sicherheit für eine Anmeldeseite:

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

9

Dies ist möglicherweise nicht die vollständige Antwort auf Ihre Frage. Wenn Sie jedoch nach einer Möglichkeit suchen, den CSF-Schutz zu deaktivieren, können Sie Folgendes tun:

@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());
    }

}

Ich habe die vollständige Konfiguration hinzugefügt, aber die Schlüsselzeile lautet:

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

2

Als @ M.Deinum schrieb schon die Antwort.

Ich habe es mit API versucht /api/v1/signup. Es umgeht den Filter / benutzerdefinierten Filter, aber eine zusätzliche Anforderung, die vom Browser aufgerufen wird. /favicon.icoDaher füge ich dies auch in web.ignoring () hinzu und es funktioniert für mich.

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

Möglicherweise ist dies für die obige Frage nicht erforderlich.


2

Wenn Sie mehrere API-Endpunkte ignorieren möchten, können Sie Folgendes verwenden:

 @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);
    }

0

Ich hatte das gleiche Problem, hier ist die Lösung: ( Erklärt )

@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.**
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.