Spring Security oauth2.0微信小程序登录

这篇具有很好参考价值的文章主要介绍了Spring Security oauth2.0微信小程序登录。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

微信小程序前期开发准备,可以参考这篇文章微信小程序前期准备
1、学习过Spring Secrity oauth2.0的都知道,他有四种登录模式可以选择
authorization code(授权码模式)
implicit(简化模式)
resource owner password credentials(密码模式)
client credentials(客户端模式)Spring Security oauth2.0微信小程序登录
前三种模式都需要用户的密码才能认证成功,客户端模式虽然不需要密码,但是也不会跟用户绑定。所以也是不符合的。我们去微信拿到用户的认证之后,需要自己的系统认证通过,然后返回token给前端。如果系统采用oauth2.0来做认证,这时候我们是没办法拿到用户的明文密码的。并且一般密码都是用BCryptPasswordEncoder加密处理,是不可逆的。这个时候,我们虽然通过了微信的认证,但是如何通过自身系统的认证就是个问题了。那么这时候就需要自定义oauth2.0的授权模式了,通过微信返回的用户唯一标识来完成认证。
这里的方法,适用用于任何的第三方登录:
首先,我们需要一个拦截器:
登录接口如下

9999端口是gateway网关端口。auth是网关路由
http://192.168.2.171:9999/auth/custom/token/social?grant_type=custom&custom=WXCUSTOM@{这后面是微信获取的code}
头信息:Basic d3hNaW5pQXBwQ3VzdG9tOnd4TWluaUFwcEN1c3RvbQ==(这后面是BASE64加密信息)


返回token格式如下:
{
    "access_token": "6c8dde52-f3e5-42a0-9de9-05244e81af37",
    "token_type": "bearer",
    "refresh_token": "012544fb-d39e-4be7-878a-3d1bba2773da",
    "expires_in": 43199,
    "scope": "server",
    "license": "made by HuaBing",
    "active": true,
    "client_id": "test"
}
标注:d3hNaW5pQXBwQ3VzdG9tOnd4TWluaUFwcEN1c3RvbQ==解密出来就是client_id:"test"

登录URL拦截器

注意这里是 filter 来接管这个请求,而不是到 Controller)

import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationEventPublisher;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author Mylucy
 * @Date 2022-01-18 10:15
 * 客户微信小程序登录
 */
public class SocialAuthenticationFilter extends AbstractAuthenticationProcessingFilter {


	private static final String SPRING_SECURITY_FORM_CUSTOM_KEY = "custom";

	@Getter
	@Setter
	private String customWxLogin = SPRING_SECURITY_FORM_CUSTOM_KEY;

	@Getter
	@Setter
	private AuthenticationEventPublisher eventPublisher;
	@Getter
	@Setter
	private boolean postOnly = true;

//	@Getter
//	@Setter
//	private AuthenticationEventPublisher eventPublisher;

	@Getter
	@Setter
	private AuthenticationEntryPoint authenticationEntryPoint;

	public SocialAuthenticationFilter() {
		super(new AntPathRequestMatcher(SecurityConstants.CUSTOM_TOKE_URL, "POST"));
	}

	/**
	 * Performs actual authentication.
	 * <p>
	 * The implementation should do one of the following:
	 * <ol>
	 * <li>Return a populated authentication token for the authenticated user, indicating
	 * successful authentication</li>
	 * <li>Return null, indicating that the authentication process is still in progress.
	 * Before returning, the implementation should perform any additional work required to
	 * complete the process.</li>
	 * <li>Throw an <tt>AuthenticationException</tt> if the authentication process
	 * fails</li>
	 * </ol>
	 *
	 * @param request  from which to extract parameters and perform the authentication
	 * @param response the response, which may be needed if the implementation has to do a
	 *                 redirect as part of a multi-stage authentication process (such as OpenID).
	 * @return the authenticated user token, or null if authentication is incomplete.
	 * @throws AuthenticationException if authentication fails.
	 */
	@Override
	@SneakyThrows
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)  {
		if (postOnly && !request.getMethod().equals(HttpMethod.POST.name())) {
			throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
		}

		String mobile = obtainMobile(request);

		if (mobile == null) {
			mobile = "";
		}

		mobile = mobile.trim();

		SocialAuthenticationToken socialAuthenticationToken = new SocialAuthenticationToken(mobile);

		setDetails(request, socialAuthenticationToken);

		Authentication authResult = null;
		try {
			authResult = this.getAuthenticationManager().authenticate(socialAuthenticationToken);

			logger.debug("Authentication success: " + authResult);
			SecurityContextHolder.getContext().setAuthentication(authResult);

		} catch (Exception failed) {
			SecurityContextHolder.clearContext();
			logger.debug("Authentication request failed: " + failed);

			eventPublisher.publishAuthenticationFailure(new BadCredentialsException(failed.getMessage(), failed),
					new PreAuthenticatedAuthenticationToken("access-token", "N/A"));

			try {
				authenticationEntryPoint.commence(request, response,
						new UsernameNotFoundException(failed.getMessage(), failed));
			} catch (Exception e) {
				logger.error("authenticationEntryPoint handle error:{}", failed);
			}
		}

		return authResult;
	}

	private String obtainMobile(HttpServletRequest request) {
		return request.getParameter(customWxLogin);
	}

	private void setDetails(HttpServletRequest request, SocialAuthenticationToken authRequest) {
		authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
	}

}

注:里面有一些常量,我这里也给出方法代码

public interface SecurityConstants {

	/**
	 * 启动时是否检查Inner注解安全性
	 */
	boolean INNER_CHECK = true;

	/**
	 * 刷新
	 */
	String REFRESH_TOKEN = "refresh_token";

	/**
	 * 验证码有效期
	 */
	int CODE_TIME = 60;

	/**
	 * 验证码长度
	 */
	String CODE_SIZE = "4";

	/**
	 * 角色前缀
	 */
	String ROLE = "ROLE_";

	/**
	 * 前缀
	 */
	String PIGX_PREFIX = "pigx_";

	/**
	 * token 相关前缀
	 */
	String TOKEN_PREFIX = "token:";

	/**
	 * oauth 相关前缀
	 */
	String OAUTH_PREFIX = "oauth:";

	/**
	 * 授权码模式code key 前缀
	 */
	String OAUTH_CODE_PREFIX = "oauth:code:";

	/**
	 * 项目的license
	 */
	String PIGX_LICENSE = "made by HuaBing";

	/**
	 * 内部
	 */
	String FROM_IN = "Y";

	/**
	 * 标志
	 */
	String FROM = "from";

	/**
	 * OAUTH URL
	 */
	String OAUTH_TOKEN_URL = "/oauth/token";

	/**
	 * 手机号登录URL
	 */
	String SMS_TOKEN_URL = "/mobile/token/sms";

	/**
	 * 社交登录URL
	 */
	String SOCIAL_TOKEN_URL = "/mobile/token/social";

	/**
	 * 自定义登录URL
	 */
	String MOBILE_TOKEN_URL = "/mobile/token/*";

	/**
	 * 客户社交登录
	 */
	String CUSTOM_TOKEN = "/custom/token/social";
	/**
	 * 客户微信登录
	 */
	String CUSTOM_TOKE_URL = "/custom/token/*";

	/**
	 * 微信获取OPENID
	 */
	String WX_AUTHORIZATION_CODE_URL = "https://api.weixin.qq.com/sns/oauth2/access_token"
			+ "?appid=%s&secret=%s&code=%s&grant_type=authorization_code";

	/**
	 * 微信小程序OPENID
	 */
	String MINI_APP_AUTHORIZATION_CODE_URL = "https://api.weixin.qq.com/sns/jscode2session"
			+ "?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";

	/**
	 * 客户微信小程序登录
	 */
	String CUSTOM_WX_MINI_LOGIN_URL = "https://api.weixin.qq.com/sns/jscode2session";
	/**
	 *  客户微信小程序登录
	 */
	String CUSTOM_WX_MINI_LOGIN_TYPE = "authorization_code";

	String CUSTOM_APPID = "";
	String CUSTOM_SECRET="";

	/**
	 * 码云获取token
	 */
	String GITEE_AUTHORIZATION_CODE_URL = "https://gitee.com/oauth/token?grant_type="
			+ "authorization_code&code=%S&client_id=%s&redirect_uri=" + "%s&client_secret=%s";

	/**
	 * 开源中国获取token
	 */
	String OSC_AUTHORIZATION_CODE_URL = "https://www.oschina.net/action/openapi/token";

	/**
	 * 码云获取用户信息
	 */
	String GITEE_USER_INFO_URL = "https://gitee.com/api/v5/user?access_token=%s";

	/**
	 * 开源中国用户信息
	 */
	String OSC_USER_INFO_URL = "https://www.oschina.net/action/openapi/user?access_token=%s&dataType=json";

	/**
	 * {bcrypt} 加密的特征码
	 */
	String BCRYPT = "{bcrypt}";

	/**
	 * sys_oauth_client_details 表的字段,不包括client_id、client_secret
	 */
	String CLIENT_FIELDS = "client_id, CONCAT('{noop}',client_secret) as client_secret, resource_ids, scope, "
			+ "authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, "
			+ "refresh_token_validity, additional_information, autoapprove";

	/**
	 * JdbcClientDetailsService 查询语句
	 */
	String BASE_FIND_STATEMENT = "select " + CLIENT_FIELDS + " from sys_oauth_client_details";

	/**
	 * 按条件client_id 查询
	 */
	String DEFAULT_SELECT_STATEMENT = BASE_FIND_STATEMENT + " where client_id = ? and del_flag = 0 and tenant_id = %s";

	/**
	 * 资源服务器默认bean名称
	 */
	String RESOURCE_SERVER_CONFIGURER = "resourceServerConfigurerAdapter";

	/**
	 * 客户端模式
	 */
	String CLIENT_CREDENTIALS = "client_credentials";

	/**
	 * 客户端编号
	 */
	String CLIENT_ID = "client_id";

	/**
	 * 用户ID字段
	 */
	String DETAILS_USER_ID = "id";

	/**
	 * 用户名
	 */
	String DETAILS_USERNAME = "username";

	/**
	 * 用户基本信息
	 */
	String DETAILS_USER = "user_info";

	/**
	 * 用户名phone
	 */
	String DETAILS_PHONE = "phone";

	/**
	 * 头像
	 */
	String DETAILS_AVATAR = "avatar";

	/**
	 * 用户部门字段
	 */
	String DETAILS_DEPT_ID = "deptId";

	/**
	 * 租户ID 字段
	 */
	String DETAILS_TENANT_ID = "tenantId";

	/**
	 * 协议字段
	 */
	String DETAILS_LICENSE = "license";

	/**
	 * 激活字段 兼容外围系统接入
	 */
	String ACTIVE = "active";

	/**
	 * AES 加密
	 */
	String AES = "aes";

}

获取客户登录的信息

注:我这里分后台用户登录,前台客户登录,不同用户查询两张不同的表

package com.pig4cloud.pigx.common.security.custom;

/**
 * @author Mylucy
 * @Date 2022-01-18 10:24
 */

import com.pig4cloud.pigx.common.security.component.PigxPreAuthenticationChecks;
import com.pig4cloud.pigx.common.security.service.PigxUserDetailsService;
import com.pig4cloud.pigx.common.security.util.PigxSecurityMessageSourceUtil;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsChecker;

/**
 * 社交登录
 */
@Slf4j
public class SocialAuthenticationProvider implements AuthenticationProvider {

	private MessageSourceAccessor messages = PigxSecurityMessageSourceUtil.getAccessor();

	private UserDetailsChecker detailsChecker = new PigxPreAuthenticationChecks();

	@Getter
	@Setter
	private PigxUserDetailsService userDetailsService;

	@Override
	@SneakyThrows
	public Authentication authenticate(Authentication authentication) {
		SocialAuthenticationToken socialAuthenticationToken = (SocialAuthenticationToken) authentication;

		String principal = socialAuthenticationToken.getPrincipal().toString();
		//这里就是获取客户信息的方法
		UserDetails userDetails = userDetailsService.customLoadBySocial(principal);
		if (userDetails == null) {
			log.debug("Authentication failed: no credentials provided");

			throw new BadCredentialsException(messages
					.getMessage("AbstractUserDetailsAuthenticationProvider.noopBindAccount", "Noop Bind Account"));
		}

		// 检查账号状态
		detailsChecker.check(userDetails);

		SocialAuthenticationToken authenticationToken = new SocialAuthenticationToken(userDetails,
				userDetails.getAuthorities());
		authenticationToken.setDetails(socialAuthenticationToken.getDetails());
		return authenticationToken;
	}

	@Override
	public boolean supports(Class<?> authentication) {
		return SocialAuthenticationToken.class.isAssignableFrom(authentication);
	}

}

获取用户信息的方法

/**
这里可以扩展你自己的用户查询方法
 * @author lengleng
 * @date 2018/8/15
 */
public interface PigxUserDetailsService extends UserDetailsService {

	/**
	 * 客户社交登录
	 *
	 * @param code 前端向微信获取的唯一标识
	 * @return
	 * @throws UsernameNotFoundException
	 */
	UserDetails customLoadBySocial(String code) throws UsernameNotFoundException;

}
==============================================分割================================================

/**
 * 用户详细信息
 *
 * @author lengleng
 */
@Slf4j
@Primary
@RequiredArgsConstructor
public class PigxUserDetailsServiceImpl implements PigxUserDetailsService {
	private final RemoteUserService remoteUserService;

	private final RemoteCustomService remoteCustomService;

	private final CacheManager cacheManager;

	private final TokenStore tokenStore;

	/**
	 * 客户社交登录
	 *
	 * @param code
	 * @return
	 * @throws UsernameNotFoundException
	 */
	@Override
	@SneakyThrows
	public UserDetails customLoadBySocial(String code) {
	//这里时远程调用查询客户表信息
		FoodMacCustom customSocialInfo = remoteCustomService.getCustomSocialInfo(code, SecurityConstants.FROM_IN).getData();
		UserDetails customDetails = getCustomDetails(customSocialInfo);
		return customDetails;
	}

	/**
	 * 构建客户信息 customDetails
	 *
	 * @param foodMacCustom
	 */
	private UserDetails getCustomDetails(FoodMacCustom foodMacCustom) {
		if (foodMacCustom == null) {
			throw new UsernameNotFoundException("客户未注册");
		}
		boolean is_lock = false;
		if (CommonConstants.CUSTOM_LOCK.equals(foodMacCustom.getStatus())) {
			is_lock = true;
		}
		if (is_lock == false) {
			throw new PigxAuth2Exception("账号已被锁定");
		}
		log.debug("用户信息::{}", foodMacCustom.getUsername());
		PigxCustomUser pigxCustomUser = new PigxCustomUser(foodMacCustom.getId(), 1, foodMacCustom.getMobile(), foodMacCustom.getAvatar(), foodMacCustom.getTenantId(),
				foodMacCustom.getUsername(), "{noop}" + foodMacCustom.getPassword(), true, true,
				true, is_lock, AuthorityUtils.NO_AUTHORITIES);
		return pigxCustomUser;

	}
}
===================================================分割==============================================================
/**
 * 系统社交登录账号表
 *
 * @author Mylucy
 * @date 2021-08-16 21:30:41
 */
public interface SysSocialDetailsService extends IService<SysSocialDetails> {
	/**
	 * 根据入参查询客户信息
	 *
	 * @param code
	 * @return
	 */
	FoodMacCustom getCustomSocialInfo(String code);
}
===================================================分割==============================================================

/**
 * @author Mylucy
 * @date 2021年08月16日
 */
@Slf4j
@AllArgsConstructor
@Service("sysSocialDetailsService")
public class SysSocialDetailsServiceImpl extends ServiceImpl<SysSocialDetailsMapper, SysSocialDetails>
		implements SysSocialDetailsService {

//注意这个方法。这个做了很多惭怍
	private final Map<String, CustomLoginHandle> customLoginHandlerMap;

	private final CacheManager cacheManager;

	private final SysUserMapper sysUserMapper;

	/**
	 * 根据入参查询客户信息
	 *
	 * @param code
	 * @return
	 */
	@Override
	public FoodMacCustom getCustomSocialInfo(String code) {
		String[] inStrs = code.split(StringPool.AT);
		String type = inStrs[0];
		String loginStr = inStrs[1];
		FoodMacCustom foodMacCustom = customLoginHandlerMap.get(type).handle(loginStr);
		return foodMacCustom;
	}
}
===================================================分割==============================================================

/**
 * @author Mylucy
 * @Date 2022-01-18 11:02
 */
public interface CustomLoginHandle {

	/***
	 * 数据合法性校验
	 * @param loginStr 通过用户传入获取微信唯一标识
	 * @return
	 */
	Boolean check(String loginStr);

	/**
	 * 通过用户传入获取微信唯一标识
	 * @param loginStr
	 * @return
	 */
	String identify(String loginStr);

	/**
	 * 通过微信openId 获取用户信息
	 * @param identify
	 * @return
	 */
	FoodMacCustom customInfo(String identify);

	/**
	 * 处理方法
	 * @param loginStr 登录参数
	 * @return
	 */
	FoodMacCustom handle(String loginStr);
}
===================================================分割==============================================================
/**
 * @author Mylucy
 * @Date 2022-01-18 11:04
 */
public abstract class AbstractCustomLoginHandler implements CustomLoginHandle {

	/***
	 * 数据合法性校验
	 * @param loginStr 通过用户传入获取唯一标识
	 * @return 默认不校验
	 */
	@Override
	public Boolean check(String loginStr) {
		return true;
	}

	/**
	 * 处理方法
	 *
	 * @param loginStr 登录参数
	 * @return
	 */
	@Override
	public FoodMacCustom handle(String loginStr) {
		if (!check(loginStr)) {
			return null;
		}

		String identify = identify(loginStr);
		FoodMacCustom foodMacCustom = customInfo(identify);
		return foodMacCustom;
	}
}
===================================================分割==============================================================

/**
 * @author Mylucy
 * @Date 2022-01-18 11:03
 */
@Slf4j
@Component("WXCUSTOM")
@AllArgsConstructor
public class CustomWeChatLoginHandler extends AbstractCustomLoginHandler {

	private final IFoodMacCustomService foodMacCustomService;

	private final SysSocialDetailsMapper sysSocialDetailsMapper;

	private final StringRedisTemplate stringRedisTemplate;

	private static final String REDIS_KEY = "WX:CUSTOM:LOGIN:";

	private final Sequence sequence;

	/**
	 * 两个小时过期
	 */
	private static final long EXPIRE_TIME = 7200000;


	/**
	 * 微信登录传入code
	 * <p>
	 * 通过code 调用qq 获取唯一标识
	 *
	 * @param code
	 * @return
	 */
	@Override
	public String identify(String code) {
		String sessionKeyOpenId = (String) stringRedisTemplate.opsForValue().get(REDIS_KEY + code);
		if (StrUtil.isEmpty(sessionKeyOpenId)) {
			SysSocialDetails condition = new SysSocialDetails();
			condition.setType(LoginTypeEnum.WECHAT.getType());
			SysSocialDetails socialDetails = sysSocialDetailsMapper.selectOne(new QueryWrapper<>(condition));
/**String url = String.format(SecurityConstants.MINI_APP_AUTHORIZATION_CODE_URL, socialDetails.getAppId(),socialDetails.getAppSecret(), code);
 String result = HttpUtil.get(sendUrl);**/
			log.debug("客户--->{}", code);

			String result = sendGet(SecurityConstants.CUSTOM_WX_MINI_LOGIN_URL,
					"appid=" + socialDetails.getAppId() + "&" +
							"secret=" + socialDetails.getAppSecret() + "&" +
							"js_code=" + code + "&" +
							"grant_type=" + SecurityConstants.CUSTOM_WX_MINI_LOGIN_TYPE);
			log.info("微信响应报文:{}", result);
			JSONObject jsonObject = JSON.parseObject(result);
			String openId = jsonObject.getString("openid");
			String sessionKey = jsonObject.getString("session_key");
			log.info("微信openId::{}", openId);
			log.info("微信sessionKey::{}", sessionKey);
			if (openId != null && !"".equals(openId)) {
				//将信息保存在redis中

				log.info("+++++++++++++微信key+++++++++++{}", sessionKey);
				String redisKey = REDIS_KEY + code;
				StringBuilder stringBuilder = new StringBuilder();
				String openIdSessionKey = stringBuilder.append(sessionKey).append("@").append(openId).toString();
//				String  openIdSessionKey= sessionKey + "#" + openId;
				stringRedisTemplate.opsForValue().set(redisKey,openIdSessionKey,EXPIRE_TIME, TimeUnit.SECONDS);
			}
			return openId;
		} else if (StrUtil.isNotEmpty(sessionKeyOpenId)) {
			String[] split = sessionKeyOpenId.split("@");
			String session = split[0];
			String openId = split[1];
			return openId;
		}
		return null;
	}

	/**
	 * openId 获取用户信息
	 *
	 * @param openId
	 * @return
	 */
	@Override
	public FoodMacCustom customInfo(String openId) {
		FoodMacCustom custom = foodMacCustomService.getOne(Wrappers.<FoodMacCustom>query().lambda()
				.eq(FoodMacCustom::getWechatopenid, openId));

		if (custom == null) {
			log.info("微信未绑定:{}", openId);
			return null;
		}
		return custom;
	}

	/**
	 * 向指定URL发送GET方法的请求
	 *
	 * @param url   发送请求的URL
	 * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
	 * @return URL 所代表远程资源的响应结果
	 */
	public static String sendGet(String url, String param) {
		String result = "";
		BufferedReader in = null;
		try {
			String urlNameString = url + "?" + param;
			URL realUrl = new URL(urlNameString);
			// 打开和URL之间的连接
			URLConnection connection = realUrl.openConnection();
			// 设置通用的请求属性
			connection.setRequestProperty("accept", "*/*");
			connection.setRequestProperty("connection", "Keep-Alive");
			connection.setRequestProperty("user-agent",
					"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			// 建立实际的连接
			connection.connect();
			// 获取所有响应头字段
			Map<String, List<String>> map = connection.getHeaderFields();
			// 遍历所有的响应头字段
			for (String key : map.keySet()) {
				System.out.println(key + "--->" + map.get(key));
			}
			// 定义 BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(
					connection.getInputStream()));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			System.out.println("发送GET请求出现异常!" + e);
			e.printStackTrace();
		}
		// 使用finally块来关闭输入流
		finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return result;
	}
}

远程调用的controller和fegin调用方法截图
Spring Security oauth2.0微信小程序登录
Spring Security oauth2.0微信小程序登录文章来源地址https://www.toymoban.com/news/detail-498428.html

生成token令牌:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.SneakyThrows;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;

import java.util.Collection;

/**
 * 第三方登录令牌
 *
 * @author Mylucy
 * @Date 2022-01-18 10:23
 */
public class SocialAuthenticationToken extends AbstractAuthenticationToken {

	private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;

	private final Object principal;

	public SocialAuthenticationToken(String mobile) {
		super(null);
		this.principal = mobile;
		setAuthenticated(false);
	}
	@JsonCreator
	public SocialAuthenticationToken(@JsonProperty("principal") Object principal,
									 @JsonProperty("authorities") Collection<? extends GrantedAuthority> authorities) {
		super(authorities);
		this.principal = principal;
		super.setAuthenticated(true);
	}

	@Override
	public Object getPrincipal() {
		return this.principal;
	}

	@Override
	public Object getCredentials() {
		return null;
	}

	@Override
	@SneakyThrows
	public void setAuthenticated(boolean isAuthenticated) {
		if (isAuthenticated) {
			throw new IllegalArgumentException(
					"Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
		}

		super.setAuthenticated(false);
	}

	@Override
	public void eraseCredentials() {
		super.eraseCredentials();
	}

}

第三方资源配置入口:


```java
package com.pig4cloud.pigx.common.security.custom;

/**
 * @author Mylucy
 * @Date 2022-01-18 10:27
 */

import com.fasterxml.jackson.databind.ObjectMapper;
import com.pig4cloud.pigx.common.security.component.PigxCommenceAuthExceptionEntryPoint;
import com.pig4cloud.pigx.common.security.handler.CustomLoginSuccessHandler;
import com.pig4cloud.pigx.common.security.service.PigxUserDetailsService;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationEventPublisher;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 *
 * 第三方登录配置入口
 * @author Mylucy
 */
@Getter
@Setter
public class SocialSecurityConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {

	@Autowired
	private ObjectMapper objectMapper;

	@Autowired
	private AuthenticationEventPublisher defaultAuthenticationEventPublisher;

	/**
	 * @Qualifier("socialLoginSuccessHandler")
	 */
	@Autowired
	private CustomLoginSuccessHandler socialLoginSuccessHandler;

	@Autowired
	private PigxUserDetailsService userDetailsService;

	@Override
	public void configure(HttpSecurity http) {
		SocialAuthenticationFilter socialAuthenticationFilter = new SocialAuthenticationFilter();
		socialAuthenticationFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
		socialAuthenticationFilter.setAuthenticationSuccessHandler(socialLoginSuccessHandler);
		socialAuthenticationFilter.setEventPublisher(defaultAuthenticationEventPublisher);
		socialAuthenticationFilter.setAuthenticationEntryPoint(new PigxCommenceAuthExceptionEntryPoint(objectMapper));

		SocialAuthenticationProvider socialAuthenticationProvider = new SocialAuthenticationProvider();
		socialAuthenticationProvider.setUserDetailsService(userDetailsService);
		http.authenticationProvider(socialAuthenticationProvider).addFilterAfter(socialAuthenticationFilter,
				UsernamePasswordAuthenticationFilter.class);
	}

}



到了这里,关于Spring Security oauth2.0微信小程序登录的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Security OAuth2.0(3):Spring Security简单入门

    Spring Security 快速入门。 本章代码已分享至Gitee:https://gitee.com/lengcz/security-spring-security qquad Spring Secutiry 是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。由于它是Spring生态系统的一员,因此它伴随着整个Spring生态系统不断修正、升级,

    2024年02月13日
    浏览(50)
  • Spring Security OAuth2.0 - 学习笔记

    OAuth2.0是一个开放标准,允许用户授权第三方应用程序访问他们存储在另外的服务提供者上的信息,而不需要将用户和密码提供给第三方应用或分享数据的所有内容。 1)授权码模式 2)简化模式 3)密码模式 4)客户端模式 普通令牌只是一个随机的字符串,没有特殊的意义,

    2024年02月16日
    浏览(50)
  • 微服务安全Spring Security Oauth2实战

    Spring Authorization Server 是一个框架,它提供了 OAuth 2.1 和 OpenID Connect 1.0 规范以及其他相关规范的实现。它建立在 Spring Security 之上,为构建 OpenID Connect 1.0 身份提供者和 OAuth2 授权服务器产品提供了一个安全、轻量级和可定制的基础。说白了,Spring Authorization Server 就是一个**认

    2024年02月03日
    浏览(39)
  • Spring Security与OAuth2的完美结合

    OAuth2是一种流行的授权框架,它允许用户授权第三方应用程序访问他们的资源。Spring Security是一个强大的安全框架,它提供了一系列的安全功能。本文将介绍如何将Spring Security与OAuth2整合,以实现更加安全和可靠的应用程序。 OAuth2的基本概念 OAuth2是一个授权框架,它允许用

    2024年02月05日
    浏览(45)
  • Spring Security实现OAuth2协议及实战

    文章篇幅较长,愿读者耐心看完。如有不足之处,请指正。 一.OAuth2介绍 1.1 OAuth2是什么 怎么用 OAuth2是目前最流行的授权协议,用来授权第三方应用,获取用户数据。 举个例子:快递员想要进入小区,有3种方式。1是业主远程开门,2是业主告诉门禁密码,3是使用令牌(Oaut

    2024年02月08日
    浏览(41)
  • Spring Security OAuth2 远程命令执行漏洞

    cd vulhub/spring/CVE-2016-4977/ docker-compose up -d 访问 http://192.168.10.171:8080/oauth/authorize?response_type=${233*233}client_id=acmescope=openidredirect_uri=http://test 用admin:admin登陆 出现以下报错,表示漏洞存在(response_type里面的命令执行了) poc.py #!/usr/bin/env python message = input(‘Enter message to encode:’) p

    2024年02月09日
    浏览(42)
  • Spring Security对接OIDC(OAuth2)外部认证

    前后端分离项目对接OIDC(OAuth2)外部认证,认证服务器可以使用Keycloak。 后端已有用户管理和权限管理,需要外部认证服务器的用户名和业务系统的用户名一致才可以登录。 后台基于Spring Boot 2.7 + Spring Security 流程: 前台浏览器跳转到  后台地址 + /login/oauth2/authorization/my-oid

    2024年02月21日
    浏览(43)
  • SpringCloud微服务整合Spring Security OAuth2

    首先得了解什么是OAuth2,这个的话可以参见博客: https://blog.csdn.net/weixin_42272869/article/details/112260123 https://www.bilibili.com/video/BV1D94y1Z7t1?p=33vd_source=bf9d70f3d2a451db07f40b6407c95a77 本文采用的是使用最广泛的、安全性最高的 授权码模式 进行讲解。 单独创建一个鉴权微服务auth,负责整个

    2024年02月09日
    浏览(54)
  • spring-security -oauth2 整合 JWT

    在这个基础上,进行整合。 spring security oauth2学习 -- 快速入门_本郡主是喵的博客-CSDN博客 先把  reids,common-pools  等依赖删掉。 删掉redis的下相关配置 1.1 导入依赖 1.2 核心代码 创建 jwtTokenConfig.java 在 AuthenticationServer.java 里面新增这些。  运行,启动!  复制这个token去官网解析

    2024年02月09日
    浏览(58)
  • Spring Security 源码解读:OAuth2 Authorization Server

    样例代码请参考:spring-security-oauth2.0-sample Spring Authorization Server刚发展不久,还没有springboot版本,而Resource Server有,但是两个底层很多不兼容,会重复引入不同版本的jar包。 另外,该 spring-security-oauth2-authorization-server 依赖支持OAuth2.1草案规范。 关于 OAuth2.1 草案介绍请参考

    2023年04月22日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包