Java Springboot 通过控制器从身份验证获取用户名

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/49529760/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 03:02:51  来源:igfitidea点击:

Springboot get username from Authentication via Controller

javaspringspring-bootspring-securityjwt

提问by Borgy Manotoy

Problem:I would like to get/extract the username/email only from authenticate.getName()... if possible, not by using parsing the string.

问题:如果可能,我只想从 authenticate.getName()... 获取/提取用户名/电子邮件,而不是使用解析字符串。

authentication.getName() or principal.getName() values:

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

In this example, I would like to get only the value of Username which is [email protected]

在此示例中,我只想获取用户名的值,即 [email protected]

Solution:

解决方案:

Since I only want to get the username/email ([email protected]), and it is returning the whole principal content/text (above), I replaced the value I set in the subject from the pricipal value... to the email value.. and it works now.

由于我只想获取用户名/电子邮件 ([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);
}

I can now get the username/email value using different ways like the one you guys are suggesting... even the one I am currently using. I do not need any special parsing now just to get the email value from the Authentication object.

我现在可以使用不同的方式来获取用户名/电子邮件值,就像你们建议的那样......甚至是我目前正在使用的那种。我现在不需要任何特殊的解析来从 Authentication 对象中获取电子邮件值。

On my previous non RESTful application using Spring... I can easily get the username using Authentication class injected in the controller method parameter.

在我以前使用 Spring 的非 RESTful 应用程序中……我可以使用注入控制器方法参数中的 Authentication 类轻松获取用户名。

Controller:

控制器:

...  
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);  
}  
...  

Console:

安慰:

[username]: [email protected]

Now, on my current project... I used a RESTful approach and after successful authentication, I am returning a token which will be used/injected in the request header. I can login using the token... but when I get the value of authentication.getName()... the return is not just the email address but it contains some other information.

现在,在我当前的项目中......我使用了 RESTful 方法,在成功验证后,我返回一个令牌,该令牌将在请求标头中使用/注入。我可以使用令牌登录……但是当我获得 authentication.getName() 的值时……返回的不仅仅是电子邮件地址,还包含一些其他信息。

Console (REST + JWT):

控制台(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

I would like to get only the username value which is "[email protected]".

我只想获得“[email protected]”的用户名值。

JWT Authentication Filter:

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 Authorization Filter:

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;
    }

}

回答by Afridi

It doesn't matter whether you are using token or basic spring security authentication as far as Authentication/Principal object is concerned.

就 Authentication/Principal 对象而言,您是使用令牌还是基本的 spring 安全身份验证并不重要。

In case of spring security, you can get your current logged in user by
1. Object user = Authentication authentication(as you are already doing)
2.

在 spring 安全的情况下,您可以通过
1获取当前登录的用户。Object user = Authentication authentication(正如您已经在做的那样)
2。

Object user = SecurityContextHolder.getContext().getAuthentication()
                    .getPrincipal();

In both cases, userwill contains the user object you returning from UserDetailsService.loadUserByUsername(...). So using default UserDetailsServiceyou will get spring security's Userobject which contains basic user information like username, passwordetc.

在这两种情况下,userwill 包含您从 返回的用户对象UserDetailsService.loadUserByUsername(...)。因此,使用默认UserDetailsService你会得到Spring Security的User对象包含了像用户的基本信息usernamepassword等等。

So in case if you are using default spring's UserDetailsService, then you can get your current logged in user simply by

因此,如果您使用默认 spring 的UserDetailsService,那么您可以通过简单地获取当前登录的用户

UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication()
                        .getPrincipal();
String username = userDetails.getUsername();

回答by Richard li

I think you can use authentication.getNameand principal.getNamein the injected controller argument of type Authenticationand Principal:

我想你可以用authentication.getNameprincipal.getName式的注入控制参数AuthenticationPrincipal

@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 "";
    }
}

could produce

可以产生

admin
-----------------
admin

回答by vaquar khan

You can use

您可以使用

import org.springframework.security.core.Authentication;

import org.springframework.security.core.context.SecurityContextHolder;

导入 org.springframework.security.core.Authentication;

导入 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("--------------------------------------------------------------");

回答by vaa

Have not seen so far any accepted answer, maybe this will help:

到目前为止还没有看到任何被接受的答案,也许这会有所帮助:

use JwtTokenUtils.debugPrint();call from below class. For other token payload see what is available inside tokenMap.

使用JwtTokenUtils.debugPrint();来自以下班级的电话。对于其他令牌有效负载,请查看内部可用的内容tokenMap

import com.fasterxml.Hymanson.core.type.TypeReference;
import com.fasterxml.Hymanson.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);
    }
}