我正在这样使用WebSecurityConfigurerAdapter
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
private UserDetailServiceImpl userDetailsService;
private BCryptPasswordEncoder bCryptPasswordEncoder;
private ApplicationUserRepository applicationUserRepository;
public WebSecurity(UserDetailServiceImpl userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder, ApplicationUserRepository applicationUserRepository) {
this.userDetailsService = userDetailsService;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
this.applicationUserRepository = applicationUserRepository;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling().authenticationEntryPoint(new AuthExceptionEntryPoint());
http.cors().and().csrf().disable().authorizeRequests()
.antMatchers(""/configuration/ui",
"/configuration/security"
"/webjars/**", "/users/social-sign-up", "client/**","/actuator/**",
"/instances","/assets/**","/home","/tables","/resources/**","/static/**",
"/css/**","/js/**","/scss/**","/templates").permitAll()
.antMatchers(HttpMethod.POST, SecurityConstants.SIGN_UP_VERIFY_URL).permitAll()
.antMatchers(HttpMethod.POST, SecurityConstants.SIGN_UP_URL).permitAll().anyRequest().authenticated()
.and().addFilter(new JWTAuthenticationFilter(authenticationManager(), applicationUserRepository))
.addFilter(new JWTAuthorizationFilter(authenticationManager()))
// this disables session creation on Spring Security
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
}
然后我有一个BasicAuthenticationFilter
这样的人
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 = JWT.require(Algorithm.HMAC512(SecurityConstants.SECRET.getBytes())).build()
.verify(token.replace(SecurityConstants.TOKEN_PREFIX, "")).getSubject();
if (user != null) {
return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
}
return null;
}
return null;
}
}
然后我有UsernamePasswordAuthenticationFilter
这样的人
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
private ApplicationUserRepository applicationUserRepository;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager,ApplicationUserRepository applicationUserRepository) {
this.authenticationManager = authenticationManager;
this.applicationUserRepository = applicationUserRepository;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
throws AuthenticationException {
try {
ApplicationUser creds = new ObjectMapper().readValue(req.getInputStream(), ApplicationUser.class);
System.err.println("Creds " + creds.getUsername() + ", " + creds.getPassword());
return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(creds.getUsername(),
creds.getPassword(), new ArrayList<>()));
} catch (Exception e) {
// e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,
Authentication auth) throws IOException, ServletException {
String token = JWT.create().withSubject(((User) auth.getPrincipal()).getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION_TIME)).sign(HMAC512(SECRET.getBytes()));
res.addHeader(HEADER_STRING, TOKEN_PREFIX + token);
res.setStatus(HttpServletResponse.SC_OK);
String userName = ((User)auth.getPrincipal()).getUsername();
ApplicationUser au= applicationUserRepository.findByUsername(userName);
String json = new ObjectMapper().writeValueAsString(au);
res.getWriter().write(json);
res.getWriter().flush();
res.getWriter().close();
}
}
这对于正常的注册和登录工作正常。我正在授权用户并在HEADER中发送JWT令牌。像这样
Authorization →Bearer awgaagarbrqe342tewrbwrewh.23tebvre34h4wbseb43qberqbqv.23gwrwvw4hw5445jmet76e-gqgqggq323t9003qgnibqp2389bvqp9q83bv9
ApplicationUser.class
就是这样
@Entity
public class ApplicationUser {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid",strategy = "uuid2")
private String id;
@Column(name = "username")
private String username;
@Column(name = "password")
private String password;
@Column(name = "name")
private String name;
@Column(name = "email")
private String email;
@Column(name = "verification_code")
private String verificationCode;
@Column(name = "verified")
private boolean verified=false;
@Column(name = "balance")
private double balance;
@JsonInclude(JsonInclude.Include.NON_NULL)
String accessToken,kun,userSocialId;
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public String getKun() {
return kun;
}
public void setKun(String kun) {
this.kun = kun;
}
public String getUserSocialId() {
return userSocialId;
}
public void setUserSocialId(String userSocialId) {
this.userSocialId = userSocialId;
}
public String getId() {
return id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getVerificationCode() {
return verificationCode;
}
public void setVerificationCode(String verificationCode) {
this.verificationCode = verificationCode;
}
public boolean isVerified() {
return verified;
}
public void setVerified(boolean verified) {
this.verified = verified;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
但是现在我需要添加社交登录/注册(Google和Facebook)。所以我在这样的控制器中做了一个方法
@PostMapping("/social-sign-up")
public ResponseEntity<ApplicationUser> signUp(String username, String name, String email, String userId, String userToken, String from) {
ApplicationUser user = new ApplicationUser();
if (from.equalsIgnoreCase("google")) {
try {
String googleTokenVerifyUrl = "https://oauth2.googleapis.com/tokeninfo?id_token="+userToken;
RestTemplate restTemplate = new RestTemplate();
GoogleVerifier googleVerifier = restTemplate.getForObject(googleTokenVerifyUrl,GoogleVerifier.class);
if(googleVerifier.getEmailVerified().equalsIgnoreCase("false")&& !googleVerifier.getEmail().equalsIgnoreCase(email)){
return new ResponseEntity<>(user, new HttpHeaders(), HttpStatus.UNAUTHORIZED);
}else{
user.setUsername(username);
user.setEmail(email);
user.setName(name);
user.setAccessToken(userToken);
user.setKun(from);
user.setUserSocialId(userId);
user.setBalance(Constants.initialBalance);
user.setVerified(true);
applicationUserRepository.save(user);
}
} catch (Exception e) {
return new ResponseEntity<>(user, new HttpHeaders(), HttpStatus.UNAUTHORIZED);
}
} else {
String getAppToken = Constants.FACEBOOK_APP_TOKEN_URL;
RestTemplate restTemplate = new RestTemplate();
FbTokenApi fbTokenApi = restTemplate.getForObject(getAppToken, FbTokenApi.class);
String verifyingToken = "https://graph.facebook.com/debug_token?input_token=" + userToken + "&access_token=" + fbTokenApi.getAccessToken();
FbTokenResponse fbTokenResponse = restTemplate.getForObject(verifyingToken, FbTokenResponse.class);
if (fbTokenResponse.getData().isIsValid()) {
//verified
user.setUsername(username);
user.setEmail(email);
user.setName(name);
user.setAccessToken(userToken);
user.setKun(from);
user.setUserSocialId(userId);
user.setBalance(Constants.initialBalance);
user.setVerified(true);
applicationUserRepository.save(user);
}else{
return new ResponseEntity<>(user, new HttpHeaders(), HttpStatus.UNAUTHORIZED);
}
}
return new ResponseEntity<>(user, new HttpHeaders(), HttpStatus.CREATED);
}
现在,我不确定如何在社交注册后如何在标头中发送JWT令牌。我是否需要完全重做身份验证和授权过程,还是可以通过在这些代码中到处进行一些更改来完成?任何帮助,将不胜感激。谢谢。