web-dev-qa-db-de.com

Federsicherheit 3 ​​- Fehler 302 immer zurückgeben

Ich benutze Spring 4, um eine einfache Anwendung zu erstellen. In letzter Zeit füge ich dem Projekt Spring Security 3 hinzu, erhalte jedoch immer den Fehlercode 302 (um immer zu home page umzuleiten).

Hier ist meine SecurityConfig :

@Configuration
@EnableWebMvcSecurity
@ComponentScan(basePackages = { "com.moon.repository" })
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication().withUser("hello").password("world").roles("USER");
}

@Override
public void configure(WebSecurity web) throws Exception {
    web
    .ignoring().antMatchers("/resources/**", "/views/**");
}

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

    http.authorizeRequests()
            .antMatchers("/","/home").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/home")
            .loginProcessingUrl("/acct/signin")
            .and()
            .logout()
            .permitAll();
}

}

Ich habe einen Controller namens AccountController :

@Controller
@RequestMapping(value = "/acct")
public class AccountController {

private final Logger logger = LoggerFactory.getLogger(AccountController.class);

@RequestMapping(value = "/signin", method = RequestMethod.POST)
public String signin(@RequestParam("username") String username,
        @RequestParam("password") String password) {

    logger.info("======== [username:{0}][password:{1}] ========", username, password);

    if ("[email protected]".equalsIgnoreCase(username)) {
        return "error";
    } else {
        return "demo";
    }
}

}

Meine WEB-INF-Struktur:

WEB-INF
----views
--------home.jsp
--------demo.jsp
--------error.jsp

Der Fluss ist wie folgt:

  1. Benutzer greifen mit http://mylocal:8080/moon auf die Website zu => es wird home.jsp angezeigt.
  2. Benutzer drücken Sie die Taste Anmelden und es öffnet sich ein Unterfenster, in dem Sie nach Benutzername und Passwort gefragt werden => immer noch in home.jsp
  3. Der Benutzer drückt den Submit-Button => Ich gehe davon aus, dass es/acct/signin und zurück zu/demo geht, aber ich sehe Fehler 302 in Google Chrome und dann geht es wieder zu/home

Irgendwelche Ideen ? Ich stecke in 2 vollen Tagen fest und jetzt bin ich fast verzweifelt ...

vielen Dank an alle, die sich mit meinem Problem befasst haben

=================================== 1. Update =========== ========================

Update: Das Formular in home.jsp

<form:form role="form" method="POST" action="acct/signin"
class="form-signin">
<div class="row">
    <div class="col-lg-5">
        <input name="username" size="20" type="email"
            class="form-control" placeholder="Email address" required
            autofocus> 
            <input name="password" type="password"
                    class="form-control" placeholder="Password" required>
                <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
    </div>
</div>
</form:form>

================================== 2. Update =========== ========================

Ich habe versucht, UserDetailsService zu implementieren (ohne In-Memory-Authentifizierung), aber immer noch ... das gleiche Problem - Fehler 302

AppUserDetailsServiceImpl.Java

@Component
public class AppUserDetailsServiceImpl implements UserDetailsService {

    private final Logger logger = LoggerFactory.getLogger(AppUserDetailsServiceImpl.class);

    @Override
    public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {

        logger.info("loadUserByUsername username=" + username);
        logger.info("======== {} ========",SecurityContextHolder.getContext().getAuthentication());

        if (!username.equals("hello")) {
            throw new UsernameNotFoundException(username + " not found");
        }

        // creating dummy user details
        return new UserDetails() {

            private static final long serialVersionUID = 2059202961588104658L;

            @Override
            public boolean isEnabled() {
                return true;
            }

            @Override
            public boolean isCredentialsNonExpired() {
                return true;
            }

            @Override
            public boolean isAccountNonLocked() {
                return true;
            }

            @Override
            public boolean isAccountNonExpired() {
                return true;
            }

            @Override
            public String getUsername() {
                return username;
            }

            @Override
            public String getPassword() {
                return "world";
            }

            @Override
            public Collection<? extends GrantedAuthority> getAuthorities() {
                List<SimpleGrantedAuthority> auths = new Java.util.ArrayList<SimpleGrantedAuthority>();
                auths.add(new SimpleGrantedAuthority("USER"));
                return auths;
            }
        };
    }

Das Protokoll zeigt:

[14/08/19 15:16:32:200][INFO ][com.moon.repository.AppUserDetailsServiceImpl][loadUserByUsername](24) loadUserByUsername username=hello
[14/08/19 15:16:32:200][INFO ][com.moon.repository.AppUserDetailsServiceImpl][loadUserByUsername](25) ======== org.springframew[email protected]f1e4f742: Principal: [email protected]; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]12afc: RemoteIpAddress: 127.0.0.1; SessionId: 023BC9A8B997ECBD826DD7C33AF55FC7; Granted Authorities: USER ========
11
chialin.lin

Ich glaube, Spring leitet Sie zu /home weiter, weil Sie einen Benutzer nicht über den Anmeldevorgang authentifiziert haben.

  1. Sie greifen über http://mylocal:8080/moon auf Ihre Web-App zu und rufen die Ansicht home.jsp auf
  2. Sie klicken auf die Schaltfläche Anmelden und übermitteln Ihr Anmeldeformular da keine Formularanmeldung explizit deklariert ist, zeigt Spring Security das Feld Benutzername und Kennwort an, in dem der Endbenutzer aufgefordert wird, seine Anmeldeinformationen einzugeben
  3. Diese Anmeldeinformationen werden dann an die Anmeldeverarbeitungs-URL (/acct/signin) weitergeleitet, für die Sie zufällig eine Zuordnung mit der Methode signin in der AccountController haben.
  4. Ein solcher Controller kann einen Benutzer nicht auf Spring-Weise authentifizieren, leitet die Anforderung jedoch durch Rückgabe eines Strings an /demo weiter
  5. Der /demo-Pfad ist für jeden nicht authentifizierten Benutzer geschützt (.anyRequest().authenticated()), da der aktuelle Benutzer tatsächlich nicht authentifiziert ist, leitet Spring Security die Anforderung automatisch auf die Anmeldeseite um
  6. Sie landen auf /home (.loginPage("/home"))

Mit einem InMemoryUserDetailsManagerConfigurer (siehe inMemoryAuthentication javadoc) können Sie sich nur über die konfigurierten Anmeldeinformationen erfolgreich anmelden. Wenn Sie ein vollwertiges Authentifizierungssystem wünschen, müssen Sie Ihrer Spring Security-Konfiguration eine UserDetailsService -Implementierung bereitstellen (über die userDetailsService -Methode).


BEARBEITEN: Nach dem Gespräch mit chialin.lin scheint die fehlende Konfiguration ein defaultSuccessfulUrl gewesen zu sein, damit Spring Security weiß, wohin der Benutzer nach der Authentifizierung umgeleitet werden soll.

7
m4rtin

Für mich kam ich aus einem etwas anderen Anwendungsfall, hatte aber "plötzlich" das gleiche Problem, bevor es perfekt funktionierte.
Mein Setup Spring mit einem ExtJs-Frontend, in das ich jetzt ein Rest-Interface einbaue.
Es hat alles super gut geklappt und dann fing ich plötzlich an http status 302 responses (WTH?)

Da ich nach folgendem Beispiel Code implementiert habe: https://octoperf.com/blog/2018/03/08/securing-rest-api-spring-security/
Es liegt eine Deklaration eines SimpleUrlAuthenticationSuccessHandlers vor.
Siehe 4.4 SecurityConfig wobei der TokenAuthenticationFilter mit einer Klasse konstruiert ist NoRedirectStrategy ; siehe 4.1 Redirect Strategy

Wenn ich dieses NoRedirectStrategy in meiner Erweiterung des AbstractAuthenticationProcessingFilter nicht eingerichtet habe, würde es mir http 302 Antworten anzeigen.

0
Dirk Schumacher

Um zu vermeiden, dass Sie eine neue einfache SuccessHandler erstellen müssen, überschreiben Sie die successfulAuthentication-Methode in Ihrem Filter und rufen Sie einfach die chain.doFilter()-Methode auf, nachdem Sie das Authentication-Objekt im Sicherheitskontext festgelegt haben.

0
Dani