[Spring Security + OAuth2 + JWT Getting Started to Practice] 23. Modify social registration based on APP interface

brief introduction

The previous chapter completed the social login, but we logged in when there is a user in the database. This chapter resolved that the database does not have that user data to complete the registration before logging in.

Technological process

Look at the previous browser code If the user is not registered we will guide the user to the registration page

Access/social/user connection after registration is complete Get user data from session via ProviderSignInUtils Help Pack

Logon binds user data from session to add to database by calling the doPostSignUp method to get the user's unique identity

Here we also see the problem that the whole process is session-based, but our APP is session-free

Reform

Innovation ideas If the third party information can not find the data in the database, save it to Redis and other users, register our platform account to get userId, then bind to save to the database

Create the help class AppSingUpUtils:

/**
 * 
 */
package com.spring.security.social;

import java.util.concurrent.TimeUnit;

import com.spring.security.AppSecretException;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.social.connect.Connection;
import org.springframework.social.connect.ConnectionData;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.WebRequest;


/**
 * app Replace providerSignInUtils in your environment to avoid unreadable social user information due to no session s
 *
 */
@Component
public class AppSingUpUtils {

	@Autowired
	private RedisTemplate<Object, Object> redisTemplate;
	
	@Autowired
	private UsersConnectionRepository usersConnectionRepository;
	
	@Autowired
	private ConnectionFactoryLocator connectionFactoryLocator;

	/**
	 * Cache social network user information to redis
	 * @param request
	 * @param connectionData
	 */
	public void saveConnectionData(WebRequest request, ConnectionData connectionData) {
		redisTemplate.opsForValue().set(getKey(request), connectionData, 10, TimeUnit.MINUTES);
	}

	/**
	 * Bind cached social site user information to system registered user information
	 * @param request
	 * @param userId
	 */
	public void doPostSignUp(WebRequest request, String userId) {
		String key = getKey(request);
		if(!redisTemplate.hasKey(key)){
			throw new AppSecretException("Cached user social account information could not be found");
		}
		ConnectionData connectionData = (ConnectionData) redisTemplate.opsForValue().get(key);
		Connection<?> connection = connectionFactoryLocator.getConnectionFactory(connectionData.getProviderId())
				.createConnection(connectionData);
		usersConnectionRepository.createConnectionRepository(userId).addConnection(connection);
		
		redisTemplate.delete(key);
	}

	/**
	 * Get redis key
	 * @param request
	 * @return
	 */
	private String getKey(WebRequest request) {
		String deviceId = request.getHeader("deviceId");
		if (StringUtils.isBlank(deviceId)) {
			throw new AppSecretException("equipment id Parameter cannot be empty");
		}
		return "imooc:security:social.connect." + deviceId;
	}

}

Exception handling

/**
 * 
 */
package com.spring.security;

public class AppSecretException extends RuntimeException {

	/**
	 * 
	 */
	private static final long serialVersionUID = -1629364510827838114L;

	public AppSecretException(String msg){
		super(msg);
	}
	
}

Extract the hkSocialSecurityConfig class:

package com.spring.security.social;

import com.spring.security.properties.SecurityConstants;
import com.spring.security.social.support.HkSpringSocialConfigurer;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;


@Component
public class SpringSocialConfigurerPostProcessor implements BeanPostProcessor {

	/* (non-Javadoc)
	 * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
	 */
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	/* (non-Javadoc)
	 * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)
	 */
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if(StringUtils.equals(beanName, "hkSocialSecurityConfig")){
			HkSpringSocialConfigurer config = (HkSpringSocialConfigurer)bean;
			config.signupUrl(SecurityConstants.DEFAULT_SOCIAL_USER_INFO_URL);
			return config;
		}
		return bean;
	}

}
/**
* url to obtain third-party user information
*/
String DEFAULT_SOCIAL_USER_INFO_URL = "/social/user";

Create an access/social/user control layer:

/**
 *
 */
package com.spring.security;

import javax.servlet.http.HttpServletRequest;

import com.spring.security.properties.SecurityConstants;
import com.spring.security.social.AppSingUpUtils;
import com.spring.security.social.support.SocialUserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.social.connect.Connection;
import org.springframework.social.connect.web.ProviderSignInUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.ServletWebRequest;


@RestController
public class AppSecurityController {

    @Autowired
    private ProviderSignInUtils providerSignInUtils;

    @Autowired
    private AppSingUpUtils appSingUpUtils;

    /**
     * Skip here when registration is required, return 401 and user information to front end
     * @param request
     * @return
     */
    @GetMapping(SecurityConstants.DEFAULT_SOCIAL_USER_INFO_URL)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public SocialUserInfo getSocialUserInfo(HttpServletRequest request) {
        SocialUserInfo socialUsrInfo = new SocialUserInfo();
        Connection<?> connection = providerSignInUtils.getConnectionFromSession(new ServletWebRequest(request));
        socialUsrInfo.setProviderId(connection.getKey().getProviderId());
        socialUsrInfo.setProviderUserId(connection.getKey().getProviderUserId());
        socialUsrInfo.setNickname(connection.getDisplayName());
        socialUsrInfo.setHeadimg(connection.getImageUrl());
        appSingUpUtils.saveConnectionData(new ServletWebRequest(request), connection.createData());
        return socialUsrInfo;
    }

}
package com.spring.security.social.support;

public class SocialUserInfo {

    private String providerId;

    private String providerUserId;

    private String nickname;

    private String headimg;

    public String getProviderId() {
        return providerId;
    }

    public void setProviderId(String providerId) {
        this.providerId = providerId;
    }

    public String getProviderUserId() {
        return providerUserId;
    }

    public void setProviderUserId(String providerUserId) {
        this.providerUserId = providerUserId;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public String getHeadimg() {
        return headimg;
    }

    public void setHeadimg(String headimg) {
        this.headimg = headimg;
    }

}

Modify the user binding method:

    /**
     * Registration and Binding
     *
     * @return
     */
    @PostMapping("/user/regist")
    public void regist(User user, HttpServletRequest request) {
        //Whether we bind or add here, we return the unique user ID tag by querying or adding
        //I'll use my username as my unique ID first
        String userId = user.getUsername();

        appSingUpUtils.doPostSignUp(new ServletWebRequest(request), userId);
    }

/user/regist er and/social/user need to be added to a configuration that does not require authentication.

The startup project was obtained by yesterday's method:

http://127.0.0.1/auth/qq?code=EC04D3F128C9C0B4926384DAAC1A5DCD&state=8883f264-8eae-4c18-a0fb-9de0c61cbcc9

Return to 401 requires APP to use users to register our platform.

Bind user accounts through/user/regist er:

Point Send returns 200, look at the database:

Now take token through social openId and providerId:

Access data:

Tags: Programming Spring Database Session Java

Posted on Fri, 20 Mar 2020 00:58:20 -0400 by hcspider