spring-security Spring Boot :获取当前用户的用户名

ej83mcc0  于 2022-11-11  发布在  Spring
关注(0)|答案(6)|浏览(169)

我尝试使用Spring的安全性获取当前登录的用户名,但Principal对象返回空值。
这是我的REST控制器方法:

@RequestMapping("/getCurrentUser")
public User getCurrentUser(Principal principal) {

    String username = principal.getName();
    User user = new User();
    if (null != username) {
        user = userService.findByUsername(username);
    }

    return user;
}

注意:我正在运行Sping Boot 1.5.13和Spring安全4.2.6

  • 这是我的安全配置类:
@Configuration

@EnableWebSecurity

public class SecurityConfig extends WebSecurityConfigurerAdapter{

    @Autowired
    private Environment env;

    @Autowired
    private UserSecurityService userSecurityService;

    private BCryptPasswordEncoder passwordEncoder() {
        return SecurityUtility.passwordEncoder();
    }

    private static final String[] PUBLIC_MATCHERS = {
            "/css/**",
            "/js/**",
            "/image/**",
            "/book/**",
            "/user/**"
    };

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().cors().disable().httpBasic().and().authorizeRequests()
        .antMatchers(PUBLIC_MATCHERS).permitAll().anyRequest().authenticated();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userSecurityService).passwordEncoder(passwordEncoder());
    }

    @Bean
    public HttpSessionStrategy httpSessionStrategy() {
        return new HeaderHttpSessionStrategy();
    }
}
  • 这是我的用户安全服务类:
@Service

public class UserSecurityService implements UserDetailsService {

private static final Logger LOG = LoggerFactory.getLogger(UserSecurityService.class);

    @Autowired 
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if(null == user) {
            LOG.warn("Username {} not found", username);
            throw new UsernameNotFoundException("Username "+username+" not found");
        }
        return user;
    }
}
  • 这是我的用户类:
@Entity

public class User implements UserDetails, Serializable {

    private static final long serialVersionUID = 902783495L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="Id", nullable=false, updatable = false)
    private Long id;

    private String username;
    private String password;
    private String firstName;
    private String lastName;

    private String email;
    private String phone;
    private boolean enabled = true;

    @OneToMany(mappedBy = "user", cascade=CascadeType.ALL, fetch = FetchType.EAGER)
    @JsonIgnore
    private Set<UserRole> userRoles = new HashSet<>();
}
jm2pwxwz

jm2pwxwz1#

有多种方法可以做到这一点。
使用SecurityContextHolder

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName();

从控制器使用Principal

@RequestMapping(value = "/myusername", method = RequestMethod.GET)
@ResponseBody
public String currentUserName(Principal principal) {
    return principal.getName();
}

HttpServletRequest开始

@RequestMapping(value = "/myusername", method = RequestMethod.GET)
@ResponseBody
public String getUsername(HttpServletRequest req) {
    return req.getUserPrincipal.getName();
}
cetgtptt

cetgtptt2#

假设您的User类实现了UserDetails,则可以从SecurityContextHolder获取User,而无需依赖注入。

public User getCurrentUser() {
  return ((User) SecurityContextHolder.getContext()
            .getAuthentication()
            .getPrincipal());
}
jxct1oxe

jxct1oxe3#

前一个答案应该可以很好地工作,如果使用spring web MVC控制器,您还可以使用springs默认方法参数解析器(org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver)将其自动注入到您的控制器中。
控制器可以执行以下操作:

@RestController
public class AcceptConnectionController {

    @PostMapping(value = "/")
    public void controllerMethod(@AuthenticationPrincipal final MyPrincipal user) {
        //...
    }

}

在上面的示例中,MyPrincipal扩展了org.springframework.security.authentication.AbstractAuthenticationToken。然后,您可以将此主体传递到服务层。

bvjxkvbb

bvjxkvbb4#

正如@cosmos所问--您是否在使用Spring Security?
如果是,则应执行以下操作:
在您的SecurityConfig:

@Bean
public AuthenticationManager customAuthenticationManager() throws Exception {
    return authenticationManager();
}

在您的控制器中:

private String getPrincipal() {
        String userName = null;
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        if (principal instanceof UserDetails) {
            userName = ((UserDetails) principal).getUsername();
        } else {
            userName = principal.toString();
        }
        return userName;
    }
vu8f3i0k

vu8f3i0k5#

下面是用于获取用户主体的方法

@PutMapping(value = "/{userId}")
public ResponseEntity<?> updateUser(@Valid @RequestBody UserPutRequest updateRequest, @PathVariable String userId,
        Authentication authentication) {
    Optional<UserObject> userOptional = userRepository.findById(userId);
    UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();
    UserObject currentUser = userRepository.findByEmail(userPrincipal.getEmail());
}
ryhaxcpt

ryhaxcpt6#

如果你正在使用keycloak,你可以用这种方式得到更多的细节

Authentication auth = SecurityContextHolder.getContext().getAuthentication();

    KeycloakPrincipal principal = (KeycloakPrincipal)auth.getPrincipal();

    KeycloakSecurityContext session = principal.getKeycloakSecurityContext();
    AccessToken accessToken = session.getToken();
    String username = accessToken.getPreferredUsername();
    String emailID = accessToken.getEmail();
    String lastname = accessToken.getFamilyName();
    String firstname = accessToken.getGivenName();
    String realmName = accessToken.getIssuer();
    AccessToken.Access realmAccess = accessToken.getRealmAccess();

相关问题