Reputation: 661
Let's imagine I have a rest services in a spring boot application.
For front end I want to login in my application and user must show own informations, such as username, userFullName, birthDay etc.
At first user must get token, then user must get user informations(username, userFullaname, birthDay) with two difference request or When user get token User must get both of them in one operation?
For example as the below code you can see I will return token.
public static void addAuthentication(HttpServletResponse res, Authentication auth) {
try {
String concattedRoles = "";
for (GrantedAuthority ga : auth.getAuthorities()) {
if (!"".equals(concattedRoles)) {
concattedRoles += "," + ga.getAuthority();
} else {
concattedRoles += ga.getAuthority();
}
}
String JWT = Jwts.builder().setSubject(auth.getName()).claim("roles", concattedRoles)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME))
.signWith(SignatureAlgorithm.HS512, SECRET).compact();
res.addHeader(HEADER_STRING, TOKEN_PREFIX + " " + JWT);//add header
res.getWriter().append("{\"token\":\""+TOKEN_PREFIX + " " + JWT+"\"}");//add body
}catch (Exception e){
e.printStackTrace();
}
}
If the above code I get userinformation from database as the below code, this way is normal way or not?
@Autowired
UserRepository userRepository;
User user = (User)auth.getPrincipal();
String username = user.getUsername();
UserEntity userEntity = userRepository.findByUsername(username);
res.getWriter().append(userEntity);//about such as.
Upvotes: 1
Views: 1301
Reputation: 661
Thank you to everyone.
Finally I solved this problem as the below.
I use UserDetails, UserDetailsService interfaces from org.springframework.security.core.userdetails package.
package com.example.notarydemo.entity;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import javax.persistence.*;
import java.util.Collection;
import java.util.List;
@Entity
@NamedStoredProcedureQueries({
@NamedStoredProcedureQuery(name = "search_user",
procedureName = "search_user",
resultClasses = {AppUser.class},
parameters = {
@StoredProcedureParameter(mode = ParameterMode.IN, name = "id", type = Integer.class),
@StoredProcedureParameter(mode = ParameterMode.IN, name = "username", type = String.class),
@StoredProcedureParameter(mode = ParameterMode.IN, name = "enabled", type = String.class),
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "cur", type = AppUser.class)
})})
@Table(name = "APP_USER", schema = "MEHMAN")
public class AppUser {
private long id;
private String username;
private String fulName;
private String encrytedPassword;
private long enabled;
private Collection<UserRole> userRolesById;
public AppUser(String userName, String fulName) {
this.username = userName;
this.fulName = fulName;
}
public AppUser() {
}
@Id
@Column(name = "ID", nullable = false, precision = 0)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@Basic
@Column(name = "USER_NAME", nullable = false, length = 36)
public String getUsername() {
return username;
}
public void setUsername(String userName) {
this.username = userName;
}
@Basic
@Column(name = "FULLNAME", nullable = false, length = 45)
public String getFULLNAME() {
return fulName;
}
public void setFULLNAME(String fullName) {
this.fulName = fullName;
}
@Basic
@Column(name = "ENCRYTED_PASSWORD", nullable = false, length = 128)
public String getEncrytedPassword() {
return encrytedPassword;
}
public void setEncrytedPassword(String encrytedPassword) {
this.encrytedPassword = encrytedPassword;
}
@Basic
@Column(name = "ENABLED", nullable = false, precision = 0)
public long getEnabled() {
return enabled;
}
public void setEnabled(long enabled) {
this.enabled = enabled;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AppUser appUser = (AppUser) o;
if (id != appUser.id) return false;
if (enabled != appUser.enabled) return false;
if (username != null ? !username.equals(appUser.username) : appUser.username != null) return false;
if (encrytedPassword != null ? !encrytedPassword.equals(appUser.encrytedPassword) : appUser.encrytedPassword != null)
return false;
return true;
}
@Override
public int hashCode() {
int result = (int) (id ^ (id >>> 32));
result = 31 * result + (username != null ? username.hashCode() : 0);
result = 31 * result + (encrytedPassword != null ? encrytedPassword.hashCode() : 0);
result = 31 * result + (int) (enabled ^ (enabled >>> 32));
return result;
}
@OneToMany(mappedBy = "appUserByUserId")
@JsonManagedReference
public Collection<UserRole> getUserRolesById() {
return userRolesById;
}
public void setUserRolesById(Collection<UserRole> userRolesById) {
this.userRolesById = userRolesById;
}
}
package com.example.notarydemo.model;
import com.example.notarydemo.entity.AppUser;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
public class MyUserPrincipal implements UserDetails {
private AppUser user;
public MyUserPrincipal(AppUser user) {
System.out.println(user.getFULLNAME() + user.getUsername() + user.getEnabled());
this.user = user;
}
public AppUser getUser() {
return user;
}
public void setUser(AppUser user) {
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getPassword() {
return user.getEncrytedPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
if (user.getEnabled() == 1)
return true;
return false;
}
}
package com.example.notarydemo.config;
import com.example.notarydemo.entity.AppUser;
import com.example.notarydemo.model.MyUserPrincipal;
import com.example.notarydemo.model.UserTokenInfoObject;
import com.example.notarydemo.repository.AppUserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private AppUserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
AppUser user = userRepository.findByUsername(username);
if (user == null)
throw new UsernameNotFoundException(username);
return new MyUserPrincipal(user);
}
}
public static void addAuthentication(HttpServletResponse res, Authentication auth) {
try {
String concattedRoles = "";
for (GrantedAuthority ga : auth.getAuthorities()) {
if (!"".equals(concattedRoles)) {
concattedRoles += "," + ga.getAuthority();
} else {
concattedRoles += ga.getAuthority();
}
}
String JWT = Jwts.builder().setSubject(auth.getName()).claim("roles", concattedRoles)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME))
.signWith(SignatureAlgorithm.HS512, SECRET).compact();
res.addHeader(HEADER_STRING, TOKEN_PREFIX + " " + JWT);
MyUserPrincipal user = (MyUserPrincipal) auth.getPrincipal();
System.out.println(user.getUser().getFULLNAME());
res.getWriter().append("{\"token\":\""+TOKEN_PREFIX + " " + JWT+"\"}");
}catch (Exception e){
e.printStackTrace();
}
}
http://www.baeldung.com/spring-security-authentication-with-a-database
Upvotes: 0
Reputation: 177
If you really want to avoid the second request to retrieve user information, you can add the user's birthdate, etc to the claims in the JWT token. Then the token itself contains everything you want to know about the user and you don't need the second trip to the database.
Be aware that this will also increase the size of the token and make encryption and decryption take longer.
Upvotes: 0
Reputation: 15878
The "only" things you need to do is create your own UserDetailsService implementation which returns your own implementation of a UserDetails object.
See here for a tutorial which implements a JPA based UserDetailsService
.
Answer adapted from https://stackoverflow.com/a/20350591/6572971
Also check other answers too on this thread.
Upvotes: 1