+ Antworten
Ergebnis 1 bis 9 von 9

Thema: Spring: Scope für Persistencer Bean (OpenJPA) in einem User-Rechte-System

  1. #1
    User Bit Themenstarter

    Registriert seit
    01.08.2013
    Fachbeiträge
    6
    Genannt
    0 Post(s)
    Hey Leute,

    Spring unterstützt ja von Hause aus die Scopes singleton, prototype, request, session und global-session (http://www.tutorialspoint.com/spring...ean_scopes.htm).

    Angenommen, ich habe ein User-Rechte-System, welches ich mit Spring Security realisiert habe. Die User-Daten werden mittels OpenJPA aus der Datenbank geholt, welche mittels eines Beans in Spring realisiert ist. Welchen von den oben genannten Scopes sollte nun dieser Bean haben, wenn ich sicherstellen möchte, dass es pro Benutzer nur eine Instanz geben soll? Wenn der Benutzer eingeloggt ist, soll beispielsweise gezählt werden, wie oft dieser eine bestimmte Aktion macht. Es soll sichergestellt werden, dass wenn der Benutzer auf mehreren Rechnern eingeloggt ist oder "zu schnell" Aktionen durchführt, dass immer noch die richtige Anzahl an Zugriffen ermittelt und geschrieben wird in die Datenbank.

    Grüße
    Dimash

  2. #2
    Global Moderator Floppy Disc
    Registriert seit
    30.07.2013
    Fachbeiträge
    839
    Genannt
    109 Post(s)
    Beschreib mal das System bessrr.
    WebApp, JEE Server, usw. ?

    Mindestens Prototype wenn nicht gar Session.
    Maven is never completely installed

  3. Es bedanken sich:
    Dimash (26.10.2014)
  4. #3
    User Bit Themenstarter

    Registriert seit
    01.08.2013
    Fachbeiträge
    6
    Genannt
    0 Post(s)
    @maki :
    Eine SpringMVC Anwendung, also mit einer Web-Oberfläche. Benutzer loggt sich über die Web-Oberfläche ein und kann dort nach bestimmten Dokumenten suchen. Diese Suche ist mittels @RequestMapping mit dem Backend verbunden, welches wiederum auf eine Lucene Architektur basiert. Innerhalb des Suchvorgangs wird auf den Persistencer Bean zugegriffen, welcher die Anzahl der Suchanfragen in die Datenbank abspeichert.
    Intuitiv hätte ich auch auf den Scope session getippt. Wo wäre der Unterschied zu global session?

  5. #4
    Frequent User Megabyte
    Registriert seit
    01.08.2013
    Fachbeiträge
    1.721
    Genannt
    111 Post(s)
    Versuchst du da gerade Spring Security nachzubauen?

  6. #5
    User Bit Themenstarter

    Registriert seit
    01.08.2013
    Fachbeiträge
    6
    Genannt
    0 Post(s)
    @cmrudolph :
    Spring Security wird von mir ebenfalls verwendet. Ich will jedoch zusätzlich pro Benutzer loggen können, wer wie oft die Suche benutzt.

  7. #6
    Frequent User Megabyte
    Registriert seit
    01.08.2013
    Fachbeiträge
    1.721
    Genannt
    111 Post(s)
    Habe in deinem Ausgangspost übersehen, dass du bereits Spring Security nutzt.
    Du gehst den falschen Weg. Du musst einen User-Provider implementieren.
    Bei mir sieht das etwa so aus:
    Java Code:
    1. import org.springframework.beans.factory.annotation.Autowired;
    2. import org.springframework.security.access.AccessDeniedException;
    3. import org.springframework.security.authentication.AuthenticationManager;
    4. import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    5. import org.springframework.security.core.Authentication;
    6. import org.springframework.security.core.AuthenticationException;
    7. import org.springframework.security.core.context.SecurityContextHolder;
    8. import org.springframework.security.core.userdetails.UserDetails;
    9. import org.springframework.security.core.userdetails.UsernameNotFoundException;
    10. import org.springframework.security.provisioning.UserDetailsManager;
    11. import org.springframework.stereotype.Component;
    12. import org.springframework.transaction.annotation.Transactional;
    13.  
    14. public class JpaUserDetailsManager implements UserDetailsManager {
    15.     private final CustomUserRepository userRepository;
    16.     @Autowired(required = false)
    17.     private AuthenticationManager authenticationManager;
    18.  
    19.     @Autowired
    20.     public JpaUserDetailsManager(CustomUserRepository userRepository) {
    21.         this.userRepository = userRepository;
    22.     }
    23.  
    24.     @Override
    25.     public void createUser(UserDetails user) {
    26.         checkType(user);
    27.         userRepository.save((CustomUser) user);
    28.     }
    29.  
    30.     @Override
    31.     public void updateUser(UserDetails user) {
    32.         checkType(user);
    33.         userRepository.save((CustomUser) user);
    34.     }
    35.  
    36.     @Override
    37.     public void deleteUser(String username) {
    38.         userRepository.deleteByUsername(username);
    39.     }
    40.  
    41.     @Transactional
    42.     @Override
    43.     public void changePassword(String oldPassword, String newPassword) throws AuthenticationException {
    44.         final Authentication currentUser = SecurityContextHolder.getContext().getAuthentication();
    45.  
    46.         if (currentUser == null)
    47.             throw new AccessDeniedException("Can't change password as no Authentication object found in context " +
    48.                     "for current user.");
    49.  
    50.         final String username = currentUser.getName();
    51.  
    52.         if (authenticationManager != null)
    53.             authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, oldPassword));
    54.  
    55.         final CustomUser user = userRepository.findByUsername(username);
    56.         user.setPassword(newPassword);
    57.         userRepository.save(user);
    58.     }
    59.  
    60.     @Override
    61.     public boolean userExists(String username) {
    62.         return userRepository.findByUsername(username) != null;
    63.     }
    64.  
    65.     @Override
    66.     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    67.         final CustomUser user = userRepository.findByUsername(username);
    68.         if (user == null) throw new UsernameNotFoundException("user not found");
    69.         return user;
    70.     }
    71.  
    72.     private void checkType(UserDetails user) {
    73.         if (!(user instanceof CustomUser)) throw new IllegalArgumentException("user must be a CustomUser");
    74.     }
    75. }
    Java Code:
    1. import org.springframework.security.core.GrantedAuthority;
    2. import org.springframework.security.core.userdetails.UserDetails;
    3.  
    4. import javax.annotation.Nonnull;
    5. import javax.persistence.*;
    6. import javax.validation.constraints.NotNull;
    7. import javax.validation.constraints.Size;
    8. import java.time.LocalDateTime;
    9. import java.util.Collection;
    10. import java.util.Collections;
    11. import java.util.EnumSet;
    12. import java.util.Set;
    13.  
    14. import static com.google.common.base.Preconditions.checkNotNull;
    15.  
    16. public class CustomUser extends AbstractEarlyIdPersistable<Long> implements UserDetails {
    17.     private static final long serialVersionUID = 7348432542539499181L;
    18.     @Column(unique = true, nullable = false, length = 32)
    19.     @Size(min = 3, max = 32)
    20.     @NotNull
    21.     private String username;
    22.     @NotNull
    23.     @Size(max = 60)
    24.     @Column(nullable = false, length = 60)
    25.     private String password;
    26.     private LocalDateTime expirationDate = null;
    27.     @NotNull
    28.     private boolean enabled = true;
    29.     @NotNull
    30.     private boolean locked = false;
    31.     @NotNull
    32.     @ElementCollection(fetch = FetchType.EAGER)
    33.     @Enumerated(EnumType.STRING)
    34.     @JoinColumn(nullable = false)
    35.     private Set<UserRole> authorities = EnumSet.noneOf(UserRole.class);
    36.     @OneToOne
    37.     private Party assignedParty;
    38.  
    39.     protected CustomUser() {
    40.     }
    41.  
    42.     CustomUser(long id, @Nonnull String username, @Nonnull String password) {
    43.         super(id);
    44.         this.username = checkNotNull(username);
    45.         this.password = checkNotNull(password);
    46.     }
    47.  
    48.     @Override
    49.     public Collection<? extends GrantedAuthority> getAuthorities() {
    50.         return Collections.unmodifiableSet(authorities);
    51.     }
    52.  
    53.     public void grantAuthority(@Nonnull UserRole role) {
    54.         authorities.add(checkNotNull(role));
    55.     }
    56.  
    57.     public void revokeAuthority(@Nonnull UserRole role) {
    58.         authorities.remove(checkNotNull(role));
    59.     }
    60.  
    61.     public boolean hasAuthority(@Nonnull UserRole role) {
    62.         return authorities.contains(checkNotNull(role));
    63.     }
    64.  
    65.     @Override
    66.     @Nonnull
    67.     public String getPassword() {
    68.         return password;
    69.     }
    70.  
    71.     public void setPassword(@Nonnull String password) {
    72.         this.password = checkNotNull(password);
    73.     }
    74.  
    75.     @Override
    76.     @Nonnull
    77.     public String getUsername() {
    78.         return username;
    79.     }
    80.  
    81.     @Override
    82.     public boolean isAccountNonExpired() {
    83.         return expirationDate == null
    84.                 || expirationDate.isAfter(LocalDateTime.now());
    85.     }
    86.  
    87.     @Override
    88.     public boolean isAccountNonLocked() {
    89.         return !locked;
    90.     }
    91.  
    92.     @Override
    93.     public boolean isCredentialsNonExpired() {
    94.         return true;
    95.     }
    96.  
    97.     @Override
    98.     public boolean isEnabled() {
    99.         return enabled;
    100.     }
    101. }
    Java Code:
    1. public interface CustomUserRepository extends JpaRepository<CustomUser, Long> {
    2.     void deleteByUsername(String username);
    3.  
    4.     CustomUser findByUsername(String username);
    5. }

    *** Edit ***

    Den CustomUser kannst du jetzt anpassen und die benötigten Daten speichern. Auf das User-Objekt kannst du mit Spring Security über den SecurityContext zugreifen. (SecurityContextHolder.getContext().getAuthentication() müsste das sein)

    *** Edit ***

    Zur Frage mit dem global session scope ein Zitat aus der Referenzdokumentation:
    The global session scope is similar to the standard HTTP Session scope (described above), and applies only in the context of portlet-based web applications. The portlet specification defines the notion of a global Session that is shared among all portlets that make up a single portlet web application. Beans defined at the global session scope are scoped (or bound) to the lifetime of the global portlet Session.
    Geändert von cmrudolph (26.10.2014 um 14:33 Uhr)

  8. Es bedanken sich:
    Dimash (26.10.2014)
  9. #7
    User Bit Themenstarter

    Registriert seit
    01.08.2013
    Fachbeiträge
    6
    Genannt
    0 Post(s)
    @cmrudolph :
    Danke für deine ausführliche Antwort. Ich habe es ähnlich implementiert, außer, dass ich nicht UserDetailsManager implementiert habe, sondern UserDetailsService.

    Vielleicht habe ich mich etwas falsch ausgedrückt. Bezüglich Autorisierung scheint es ja von Spring Security schon geregelt zu sein.
    Meine Frage ist folgende (diesmal mit bisschen Code hinterlegt):

    SearchSystem:
    Java Code:
    1.  
    2.     @Autowired CustomPersistencer persistencer;
    3.     @RequestMapping(value = { "/members/search" }, method = RequestMethod.GET)
    4.     public void search(HttpServletRequest request, HttpServletResponse response) {
    5.         JSONObject result = buildSearchResult(searchRequestData);
    6.         sendResultObjectToClient(result, response);
    7.         persistencer.countAccess();
    8.     }

    Und der dazugehörige Bean:
    Java Code:
    1.  
    2.     @Bean
    3.     public CustomPersistencer getPersistencer() {
    4.         return new CustomPersistencer();
    5.     }

    Angenommen, countAccess() erhöht für den jeweiligen Benutzer die Anzahl der Zugriffe und schreibt das in die Datenbank. Es soll nur eine Instanz des CustomPersistencer pro eingeloggten Benutzer vorhanden sein. Welchen Scope nehme ich da jetzt?

  10. #8
    Frequent User Megabyte
    Registriert seit
    01.08.2013
    Fachbeiträge
    1.721
    Genannt
    111 Post(s)
    Ok, ich glaube mein Ansatz war etwas vorschnell. Die Daten direkt an das "Nutzerprofil" zu binden, passt nicht so richtig, weil die Daten wohl nicht so eng damit gekoppelt sind.
    Die Session erscheint mir der beste Gültigkeitsbereich. Die Session überdauert aber den Login eines Benutzers, sodass du dich um Initialisierung beim Login / Aufräumen beim Logout selbst kümmern musst. Problematisch könnte es auch werden, wenn derselbe Nutzer mehrfach eingeloggt ist (wobei ich auch nicht weiß, ob es in diesem Fall dann mehrere UserDetails-Instanzen vom selben Nutzer gibt).

  11. Es bedanken sich:
    Dimash (26.10.2014)
  12. #9
    User int Avatar von Katharsas
    Registriert seit
    02.03.2014
    Fachbeiträge
    42
    Genannt
    1 Post(s)
    *ausgrab*
    Ich würde den Zähler direkt im CustomUser speichern. Z.b. jeder User erzeugt bei Kontruktion 1 Zählerobjekt, zum zählen musst du über den User drauf zugreifen. Session Scope geht nicht, da ein User mehrere Sessions gleichzeitig haben kann.

    Um immer auf Objekte mit "User Scope" zugreifen zu können, setze ich die Referenz auf den eingeloggten User in meiner Session-scoped Klasse. Ein Objekt dieser Klasse wire ich dann in alle Controller welche Login voraussetzen, sodass immer ein eingeloggter User von der Session gefunden werden kann. Session Scoped Objekte musst du mit ScopedProxyMode wiren.
    Gothic Reloaded Mod: www.gothic-reloaded-mod.de

+ Antworten Thema als "gelöst" markieren

Direkt antworten Direkt antworten

Nenne ein Edelgas!

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)

Ähnliche Themen

  1. Antworten: 0
    Letzter Beitrag: 06.06.2014, 13:11
  2. Windows Admin Rechte
    Von groggy im Forum Software
    Antworten: 2
    Letzter Beitrag: 30.04.2014, 21:11
  3. Rechte an Postings/ Löschen
    Von schlingel im Forum Spielwiese
    Antworten: 6
    Letzter Beitrag: 14.08.2013, 11:12
  4. Thema als erledigt markieren-Rechte
    Von Swoop im Forum Kritiken & Anregungen
    Antworten: 16
    Letzter Beitrag: 09.08.2013, 08:00
  5. Bean Validation unique Strings
    Von schmitt19 im Forum Java Enterprise Edition (Java EE)
    Antworten: 3
    Letzter Beitrag: 28.07.2013, 20:29

Berechtigungen

  • Neue Themen erstellen: Ja
  • Themen beantworten: Ja
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •