La mia logica di accesso dovrebbe far parte del controller o di un servizio in webapp MVC

4

Sto utilizzando Shiro come responsabile della sicurezza per un'applicazione web MVC di Spring.

Il login avviene fondamentalmente in queste righe:

Subject user = SecurityUtils.getSubject();
user.login(new UsernamePasswordToken(username, password));

Dove dovrei inserire questa logica? login() può generare eccezioni se l'utente richiesto non esiste o è stata fornita una password errata, ecc. Devo chiamare il codice dal mio controller e gestire l'errore lì o dovrei chiamarlo dal mio livello di servizio, rilevare eccezioni e rethrow mio fino al controller?

    
posta Sotirios Delimanolis 11.02.2013 - 05:12
fonte

2 risposte

6

Una delle due opzioni che presenti è valida.

I servizi (il livello Model) sono autorizzati a chiamare altri servizi. Quindi avere il tuo servizio chiama il servizio di autenticazione è accettabile.

Allo stesso modo, i controllori possono chiamare i servizi in modo che l'opzione sia ugualmente accettabile.

Se Shiro sta fornendo i tuoi soli meccanismi di autenticazione, allora è una specie di disapprovazione tra entrambi gli approcci. Chiamare dal controller sembrerebbe un po 'più veloce da sviluppare e potenzialmente meno codice di gestione degli errori.

Tuttavia, se si intende aggiungere ulteriori controlli / involucri intorno a tale chiamata di autenticazione, è necessario che il proprio modello effettui la chiamata. Quindi, se c'è una probabile chiamata aggiuntiva per l'autorizzazione dopo il controllo dell'autenticazione, allora mi proverò a chiamare dal Modello.

Nota rapida, definizioni allentate:
Autenticazione : "Sono io che dico di essere?"
Autorizzazione : "Ho l'autorità o permesso di accedere a questo? "

    
risposta data 11.02.2013 - 22:07
fonte
7

Dovrebbe essere in un livello di servizio.

public interface UserService {
    public void findByLogin(final String userName);
}

E in un'implementazione del servizio:

public class UserServiceImpl implements UserService {

    @Inject
    private UserRepository userRepository;

    public User findByLogin(final String userName, final String password) {
        Preconditions.checkArgument(!Strings.isNullOrEmpty(userName), "Username is mandatory !");
        return Preconditions.checkNotNull(userRepository.findByLogin(userName), "User not found !");
    }
}

E un servizio di provider di identità:

public class InternalIdentityProviderImpl implements ... {

    @Inject
    private UserService userService;

    public void authenticate(final String login, final String password) throws BadCredentialsException, IdentityNotFoundException {
        try {
            Preconditions.checkArgument(!Strings.isNullOrEmpty(login), "Username is mandatory !");
            Preconditions.checkArgument(!Strings.isNullOrEmpty(password), "Username is mandatory !");
        catch(Exception e) {
            throw new BadCredentialsException(e);
        }

        // Check user 
        try {
            User internal = Preconditions.checkNotNull(userService.findByLogin(username));
        } catch(Exception e) {
            // logs
            throw new IdentityNotFoundException(e);
        }

        // Shiro authentication 
        Subject user = SecurityUtils.getSubject();
        user.login(new UsernamePasswordToken(username, password));
    }

}

Dovresti personalizzare il modo in cui l'utente viene richiamato dal provider di identità e come viene convalidato dal tuo sistema di identificazione.

Attualmente ho usato RuntimeException lanciata da Guava Preconditions, ma puoi usare una specifica eccezione Handcrafted.

vale a dire:

  • IdentityNotFoundException: dal tuo provider di identità.
  • BadCredentialsException: dal tuo sistema di identificazione.

Questo servizio potrebbe essere chiamato dal controller e gestire l'eccezione per visualizzare il messaggio corretto.

    
risposta data 11.02.2013 - 22:35
fonte

Leggi altre domande sui tag