Проблема: Я хотел бы получить / извлечь имя пользователя / адрес электронной почты только из Authenticate.getName () ... если возможно, не используя синтаксический анализ строки.
Значения authentication.getName () или Principal.getName ():
[username]: org.springframework.security.core.userdetails.User@21463e7a: Username: [email protected]; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities
В этом примере я хотел бы получить только значение имени пользователя, которое является [email protected].
Решение:
Поскольку я хочу получить только имя пользователя / адрес электронной почты ([email protected]), и он возвращает весь основной контент / текст (см. Выше), я заменил значение, которое я установил в теме, с основного значения ... на значение электронной почты .. и теперь он работает.
@Override
protected void successfulAuthentication(HttpServletRequest req,
HttpServletResponse res,
FilterChain chain,
Authentication auth) throws IOException, ServletException {
String email = auth.getName();
String principal = auth.getPrincipal().toString();
Date expiration = new Date(System.currentTimeMillis() + SecurityConstants.EXPIRATION_TIME);
String token = Jwts.builder()
.setSubject(email) //from principal to email
.setExpiration(expiration)
.signWith(SignatureAlgorithm.HS512, SecurityConstants.SECRET.getBytes())
.compact();
AuthenticatedUser loginUser = new AuthenticatedUser(email);
loginUser.setToken(token);
String jsonUser = Util.objectToJsonResponseAsString(loginUser, "user");
res.addHeader(SecurityConstants.HEADER_STRING, SecurityConstants.TOKEN_PREFIX + token);
res.setContentType("application/json");
res.setCharacterEncoding(ConstantUtil.DEFAULT_ENCODING);
res.getWriter().write(jsonUser);
}
Теперь я могу получить имя пользователя / адрес электронной почты, используя разные способы, такие как тот, который вы предлагаете ... даже тот, который я использую в настоящее время. Мне не нужен сейчас какой-либо специальный синтаксический анализ, чтобы получить значение электронной почты из объекта аутентификации.
В моем предыдущем приложении без RESTful с использованием Spring ... я могу легко получить имя пользователя, используя класс аутентификации, введенный в параметр метода контроллера.
Контроллер:
...
public Ticket getBySwertresNo(Authentication authentication, @PathVariable String swertresNo) {
logger.debug("Inside getBySwertresNo: " + swertresNo);
System.out.println("\n[username]: " + authentication.getName() + "\n");
return m_sugalService.getSwertresInfoBySwertresNo(swertresNo);
}
...
Приставка:
[username]: [email protected]
Теперь, в моем текущем проекте ... Я использовал подход RESTful, и после успешной аутентификации я возвращаю токен, который будет использоваться / вводиться в заголовок запроса. Я могу войти в систему, используя токен ... но когда я получаю значение authentication.getName () ... возвращается не только адрес электронной почты, но и некоторая другая информация.
Консоль (REST + JWT):
[username]: org.springframework.security.core.userdetails.User@21463e7a: Username: [email protected]; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities
Я хотел бы получить только значение имени пользователя: «[email protected]».
Фильтр аутентификации JWT:
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest req,
HttpServletResponse res) throws AuthenticationException {
String username = req.getParameter("username");
String password = req.getParameter("password");
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
Authentication authentication = authenticationManager.authenticate(authenticationToken);
return authentication;
}
@Override
protected void successfulAuthentication(HttpServletRequest req,
HttpServletResponse res,
FilterChain chain,
Authentication auth) throws IOException, ServletException {
String email = auth.getName();
String principal = auth.getPrincipal().toString();
Date expiration = new Date(System.currentTimeMillis() + SecurityConstants.EXPIRATION_TIME);
String token = Jwts.builder()
.setSubject(principal)
.setExpiration(expiration)
.signWith(SignatureAlgorithm.HS512, SecurityConstants.SECRET.getBytes())
.compact();
AuthenticatedUser loginUser = new AuthenticatedUser(email);
loginUser.setToken(token);
String jsonUser = Util.objectToJsonResponseAsString(loginUser, "user");
res.addHeader(SecurityConstants.HEADER_STRING, SecurityConstants.TOKEN_PREFIX + token);
res.setContentType("application/json");
res.setCharacterEncoding(ConstantUtil.DEFAULT_ENCODING);
res.getWriter().write(jsonUser);
}
}
Фильтр авторизации JWT:
public class JWTAuthorizationFilter extends BasicAuthenticationFilter {
public JWTAuthorizationFilter(AuthenticationManager authManager) {
super(authManager);
}
@Override
protected void doFilterInternal(HttpServletRequest req,
HttpServletResponse res,
FilterChain chain) throws IOException, ServletException {
String header = req.getHeader(SecurityConstants.HEADER_STRING);
if (header == null || !header.startsWith(SecurityConstants.TOKEN_PREFIX)) {
chain.doFilter(req, res);
return;
}
UsernamePasswordAuthenticationToken authentication = getAuthentication(req);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(req, res);
}
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
String token = request.getHeader(SecurityConstants.HEADER_STRING);
if (token != null) {
// parse the token.
String user = Jwts.parser()
.setSigningKey(SecurityConstants.SECRET.getBytes())
.parseClaimsJws(token.replace(SecurityConstants.TOKEN_PREFIX, ""))
.getBody()
.getSubject();
if (user != null) {
return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
}
return null;
}
return null;
}
}
Просто хотел отметить, что RESTfulness не имеет ничего общего с тем, используете ли вы JWT или нет.
Спасибо за заметку, я новичок в REST, кстати. Я попытался отладить контроллер, но получаю все длинное строковое значение, а не отдельные строки.
вы получаете весь объект, потому что это то, что вы передаете в: String token = Jwts.builder (). setSubject (Principal). Вы можете изменить это, чтобы использовать электронную почту, или просто введите имя пользователя, а затем выполните поиск этого пользователя позже.
@BorgyManotoy Есть какие-нибудь обновления для этого?




Что касается объекта Authentication / Principal, не имеет значения, используете ли вы токен или базовую проверку подлинности Spring Security.
В случае весенней безопасности вы можете получить текущего авторизованного пользователя по
.
1. Object user = Authentication authentication (как вы уже делаете)
2.
Object user = SecurityContextHolder.getContext().getAuthentication()
.getPrincipal();
В обоих случаях user будет содержать объект пользователя, возвращаемый вами из UserDetailsService.loadUserByUsername(...). Таким образом, используя UserDetailsService по умолчанию, вы получите объект Spring Security User, который содержит основную информацию о пользователе, такую как username, password и т. д.
Так что, если вы используете Spring UserDetailsService по умолчанию, вы можете получить текущего пользователя, вошедшего в систему, просто с помощью
UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication()
.getPrincipal();
String username = userDetails.getUsername();
Невозможно передать пользователю
Я думаю, вы можете использовать authentication.getName и principal.getName во введенном аргументе контроллера типа Authentication и Principal:
@Controller
@RequestMapping("/info")
public class GetNameController {
@RequestMapping(value = "/name", method = RequestMethod.GET)
public String getName(Authentication authentication, Principal principal) {
System.out.println(authentication.getName());
System.out.println("-----------------");
System.out.println(principal.getName());
return "";
}
}
мог произвести
admin
-----------------
admin
Те же результаты: org.springframework.security.core.userdetails.User@21463e7a: Имя пользователя: [email protected]; Пароль защищен]; Включено: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Не предоставлено никаких полномочий
Ты можешь использовать
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
System.out.println("--------------------------------------------------------------");
JwtUser jwtUser = (JwtUser) auth.getPrincipal();
//Get the username of the logged in user: getPrincipal()
System.out.println("auth.getPrincipal()=>"+jwtUser.getUsername() );
//Get the password of the authenticated user: getCredentials()
System.out.println("auth.getCredentials()=>"+auth.getCredentials());
//Get the assigned roles of the authenticated user: getAuthorities()
System.out.println("auth.getAuthorities()=>"+auth.getAuthorities());
//Get further details of the authenticated user: getDetails()
System.out.println("auth.getDetails()=>"+auth.getDetails());
System.out.println("--------------------------------------------------------------");
Пока не видел ни одного принятого ответа, возможно, это поможет:
используйте вызов JwtTokenUtils.debugPrint(); из класса ниже. Для другой полезной нагрузки токена посмотрите, что доступно внутри tokenMap.
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.*;
import static org.springframework.security.oauth2.provider.token.AccessTokenConverter.EXP;
public class JwtTokenUtils {
private static final Logger logger = LoggerFactory.getLogger(JwtTokenUtils.class);
private static Format dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static ObjectMapper objectMapper = new ObjectMapper();
public static void debugPrint() {
try {
Map<String, Object> tokenMap = decode(getToken());
logger.debug("JwtTokenUtils:debugPrint jwt:"
+ " user_name {" + tokenMap.get("user_name")
+ "}, expired {" + convertTime((long)tokenMap.get(EXP))
+ "}");
} catch (Exception e) {
logger.error("JwtTokenUtils:debugPrint exception: " + e);
}
}
private static String getToken() {
return getAuthorizationHeader().split(" ")[1];
}
private static String getAuthorizationHeader() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
return request.getHeader("Authorization");
}
private static Map<String, Object> decode(String token) {
try {
Jwt jwt = JwtHelper.decode(token);
String claimsStr = jwt.getClaims();
TypeReference<HashMap<String,Object>> typeRef = new TypeReference<>() {};
return objectMapper.readValue(claimsStr, typeRef);
}
catch (Exception e) {
throw new InvalidTokenException("Cannot convert access token to JSON", e);
}
}
private static String convertTime(long time){
Date date = new Date(time * 1000);
return dateFormat.format(date);
}
}
почему бы вам не поставить точку останова в вашем контроллере и не проверить значение объекта аутентификации?