第三方登录_微博

1.微博配置文件:

#第三方微博登录配置
constants:
    #WEIBO
    weiBoAppId: ******(微博平台的AppID)
    weiBoAppSecret: ********(微博平台的AppSecret)
    weiBoRedirectUrl: ********(登录成功后的回调路径:http://www.****.com/api/v1/anon/weibo_login)
    weiBoTokenUrl: https://api.weibo.com/oauth2/access_token(微博token路径)
    weiBoUrl: https://api.weibo.com/oauth2/authorize? (访问微博路径)
    weiBoOpenId: uid
    clientId: ****-****-***-***-***** (客户端id)
    url: http://uc.***.com (跳转首页,注册页的路径域名)

2.微博第三方登录:常量配置类

package com.ciip.cloud.core.usercenter.constants;

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import javax.validation.constraints.NotEmpty;

/**
 * Title: ThirdLoginConstants
 * Description: 微博第三方登录:常量配置类
 *
 * @author 
 * @created 2019/5/7 14:10
 */
@Configuration
@ConfigurationProperties(prefix = "constants")
@Getter
@Setter
public class ThirdLoginConstants {


    /**
     * 微博的AppID
     */
    @NotEmpty
    private String weiBoAppId;

    /**
     * 微博的AppSecret
     */
    @NotEmpty
    private String weiBoAppSecret;

    /**
     * 微博的回调路径
     */
    @NotEmpty
    private String weiBoRedirectUrl;
    /**
     * 微博token路径
     */
    @NotEmpty
    private String weiBoTokenUrl;
    /**
     * 微博访问路径
     *          
     */
    @NotEmpty
    private String weiBoUrl;
    /**
     * 微博uid
     *          
     */
    @NotEmpty
    private String weiBoOpenId;
     /**
     * clientId
     *         
     */
    @NotEmpty
    private String clientId;
    /**
     * 域名路径
     *          
     */
    @NotEmpty
    private String url;


}

3.controller层:

package com.ciip.cloud.core.usercenter.controller;
/**
 * Title: ThirdLoginController
 * Description: 微博第三方登录
 *
 * @author 
 * @created 2019/5/14 10:57
 */

import com.ciip.cloud.core.common.constant.usercenter.CIIPCommonConstant;
import com.ciip.cloud.core.usercenter.service.WeiBoAuthService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;

@Api(value = "ThirdLoginController", description = "第三方登录(微信,QQ,微博)")
@RestController
@RequestMapping(value = CIIPCommonConstant.ApiPath.V1, produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
public class ThirdLoginController {


    @Autowired
    WeiBoAuthService weiBoAuthService;

    /**
     * CIIP改版:微博登陆页面
     *               2019-05-20
     *
     * @return
     */
    @GetMapping(value =  CIIPCommonConstant.ApiAuth.ANON +"/weibo_loginUrl")
    public String getWeiBoCode(){
        return weiBoAuthService.getWeiBoCode();
    }

    /**
     * CIIP改版:微博获取token
     *               2019-05-22
     * @param code
     * @param response
     * @return
     */
    @GetMapping(value = CIIPCommonConstant.ApiAuth.ANON +"/weibo_accessToken")
    public String getWeiBoAccessToken(String code,HttpServletResponse response)throws Exception{
        return weiBoAuthService.getWeiBoAccessToken(code,response);
    }

}

4.service层:

package com.ciip.cloud.core.usercenter.service;

import javax.servlet.http.HttpServletResponse;

/**
 * Title: WeiBoAuthService
 * Description: 微博 认证接口
 *
 * @author 
 * @created 2019/5/20 17:30
 */

public interface WeiBoAuthService {

    /**
     * 获取WeiBoCode
     *               2019-05-20
     * @return
     */
    String getWeiBoCode();

    /**
     * 获取WeiBoToken
     *               2019-05-20
     * @return
     */
    String getWeiBoAccessToken(String code, HttpServletResponse response) throws Exception;

}

5.service实现层:

package com.ciip.cloud.core.usercenter.service.impl;

import cn.hutool.core.util.StrUtil;
import com.ciip.cloud.core.common.constant.enums.usercenter.CiipRegisterType;
import com.ciip.cloud.core.usercenter.constants.ThirdLoginConstants;
import com.ciip.cloud.core.usercenter.model.CiipTokenLog;
import com.ciip.cloud.core.usercenter.service.CiipTokenLogService;
import com.ciip.cloud.core.usercenter.service.WeiBoAuthService;
import com.ciip.cloud.core.usercenter.utils.HttpClientUtil;
import com.ciip.cloud.core.usercenter.utils.URLEncodeUtil;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.Date;

import static com.ciip.cloud.core.common.constant.usercenter.CIIPCommonConstant.OAUTH_LOGIN_URL.WEIBO_LOGIN;
import static org.springframework.security.oauth2.common.OAuth2AccessToken.ACCESS_TOKEN;
import static org.springframework.security.oauth2.common.OAuth2AccessToken.EXPIRES_IN;

/**
 * Title: WeiBoAuthServiceImpl
 * Description:  微博 实现层
 *
 * @author 
 * @created 2019/5/20 17:31
 */

@Service
public class WeiBoAuthServiceImpl implements WeiBoAuthService {


    @Autowired
    ThirdLoginConstants thirdLoginConstants;
    @Autowired
    CiipTokenLogService ciipTokenLogService;

    /**
     * 获取WeiBoCode
     *               2019-05-20
     * @return
     */
    @Override
    public String getWeiBoCode() {
        //拼接url
        StringBuilder url = new StringBuilder();
        url.append(thirdLoginConstants.getWeiBoUrl());
        url.append("client_id=").append(thirdLoginConstants.getWeiBoAppId());
        //回调地址 ,回调地址要进行Encode转码
        String redirect_uri = thirdLoginConstants.getWeiBoRedirectUrl();
        //转码
        url.append("&redirect_uri=").append(URLEncodeUtil.getURLEncoderString(redirect_uri));
        url.append(WEIBO_LOGIN);
        url.append("&response_type=code");
        System.out.println(url.toString());
        return  url.toString();
    }

    /**
     * 获取WeiBoToken
     *               2019-05-20
     *
     * @return
     */
    @Override
    public String getWeiBoAccessToken(String code,HttpServletResponse response) throws Exception {
        int expires_in;
        String access_token = "";
        String refresh_token = "";
        String openid = "";
        String params = "client_id=" + thirdLoginConstants.getWeiBoAppId()
                + "&client_secret=" + thirdLoginConstants.getWeiBoAppSecret()
                + "&grant_type=authorization_code"
                + "&redirect_uri=" + thirdLoginConstants.getWeiBoRedirectUrl()+WEIBO_LOGIN
                + "&code=" + code;
        // 用code换取accessToken
        String url = HttpClientUtil.postUrl(thirdLoginConstants.getWeiBoTokenUrl(), params);
        //String url = HttpClientUtils.postParameters("https://api.weibo.com/oauth2/access_token", params);
        JSONObject jsonObject = new JSONObject(url);

        access_token = jsonObject.getString(ACCESS_TOKEN);
        openid = jsonObject.getString(thirdLoginConstants.getWeiBoOpenId());
        expires_in =(int)jsonObject.get(EXPIRES_IN);
        //refresh_token = jsonObject.getString(REFRESH_TOKEN);

        if(StrUtil.isNotEmpty(openid)){
            //根据openid,获取token表信息
            CiipTokenLog tokenLog =  ciipTokenLogService.findBySourceId(openid);
            if(null != tokenLog){
                //token 信息的修改
                tokenLog.setExpiresIn(expires_in);
                tokenLog.setAccessToken(access_token);
                tokenLog.setRefreshToken(refresh_token);
                tokenLog.setModifyDate(new Date());
                ciipTokenLogService.saveCiipTokenLog(tokenLog);

            }else{
                //token 信息的添加
                CiipTokenLog ciipTokenLog = new CiipTokenLog();
                ciipTokenLog.setAccessToken(access_token);
                ciipTokenLog.setExpiresIn(expires_in);
                ciipTokenLog.setRefreshToken(refresh_token);
                ciipTokenLog.setOpenId(openid);
                ciipTokenLog.setRegisterType(CiipRegisterType.weixin);
                ciipTokenLog.setCreateDate(new Date());
                ciipTokenLogService.saveCiipTokenLog(ciipTokenLog);
            }
        }
        return openid;
    }
}

6.安全配置(SecurityConfig):

package com.ciip.cloud.core.usercenter.oauth;

import com.ciip.cloud.core.usercenter.handler.CustomAccessDeniedHandler;
import com.ciip.cloud.core.usercenter.handler.CustomAuthenticationFailureHandler;
import com.ciip.cloud.core.usercenter.oauth.moblie.SmsAuthenticationConfig;
import com.ciip.cloud.core.usercenter.oauth.moblie.SmsCodeFilter;
import com.ciip.cloud.core.usercenter.oauth.qq.QQCodeFilter;
import com.ciip.cloud.core.usercenter.oauth.qq.QqAuthenticationConfig;
import com.ciip.cloud.core.usercenter.oauth.weiBo.WeiBoAuthenticationConfig;
import com.ciip.cloud.core.usercenter.oauth.weiBo.WeiBoCodeFilter;
import com.ciip.cloud.core.usercenter.oauth.weiXin.WeiXinAuthenticationConfig;
import com.ciip.cloud.core.usercenter.oauth.weiXin.WeiXinCodeFilter;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;


@Configuration
@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    UserDetailsService userDetailsService;

    @Autowired
    CustomAuthenticationFailureHandler customAuthenticationFailureHandler;

    @Autowired
    CustomAccessDeniedHandler customAccessDeniedHandler;


    @Autowired
    private SmsAuthenticationConfig smsAuthenticationConfig;

    @Autowired
    private QqAuthenticationConfig qqAuthenticationConfig;
    @Autowired
    private WeiXinAuthenticationConfig weiXinAuthenticationConfig;
    @Autowired
    private WeiBoAuthenticationConfig weiBoAuthenticationConfig;
    @Autowired
    private SmsCodeFilter smsCodeFilter;
    @Autowired
    private WeiXinCodeFilter weiXinCodeFilter;
    @Autowired
    private WeiBoCodeFilter weiBoCodeFilter;
    @Autowired
    private QQCodeFilter qqCodeFilter;

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception { // @formatter:off

        http
                // 头部缓存
                .headers()
                .cacheControl()
                .and()
                // 防止网站被人嵌套
                .frameOptions()
                .sameOrigin();

        http
                .addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加短信验证码校验过滤器
                .addFilterBefore(weiXinCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加weixin验证码校验过滤器
                .addFilterBefore(weiBoCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加weiBo验证码校验过滤器
                .addFilterBefore(qqCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加QQ验证码校验过滤器
                .formLogin().failureHandler(customAuthenticationFailureHandler).and()
                .authorizeRequests() // 授权配置
                .antMatchers("/login","/api/v1/anon/**","/oauth/authorize","/oauth/token").permitAll() // 无需认证的请求路径
//                .anyRequest()  // 所有请求
//                .authenticated() // 都需要认证
                .and()
                .csrf().disable()
                .apply(smsAuthenticationConfig)//短信验证
                .and().apply(qqAuthenticationConfig) // 第三方QQ登录验证
                .and().apply(weiXinAuthenticationConfig) // 第三方WeiXin登录验证
                .and().apply(weiBoAuthenticationConfig); // 第三方微博登录验证



        http.exceptionHandling().accessDeniedHandler(customAccessDeniedHandler);


    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off
        auth.userDetailsService(userDetailsService).passwordEncoder(customPasswordEncoder());
    } // @formatter:on

    //TODO 为了符合原有BIM用户加密方式,所以自定义加密规则
    @Bean
    public PasswordEncoder customPasswordEncoder() {
        return new PasswordEncoder() {
            @Override
            public String encode(CharSequence rawPassword) {
                return DigestUtils.md5Hex(rawPassword.toString());
            }
            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                return DigestUtils.md5Hex(rawPassword.toString()).equals(encodedPassword);
            }
        };
    }
//    //TODO 采用内置加密方式,存储数据库格式如:'{MD5}e10adc3949ba59abbe56e057f20f883e'
    @Bean
    PasswordEncoder passwordEncoder(){
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
}

7.微博身份验证配置:

package com.ciip.cloud.core.usercenter.oauth.weiBo;

import com.ciip.cloud.core.usercenter.handler.CustomAuthenticationFailureHandler;
import com.ciip.cloud.core.usercenter.service.CiipUserService;
import org.springframework.beans.factory.annotation.Autowired;
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;
import org.springframework.stereotype.Component;

/**
 * Title: WeiBoAuthenticationConfig
 * Description: TODO
 *
 * @author 
 * @created 2019-05-23
 */
@Component
public class WeiBoAuthenticationConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {

    @Autowired
    CustomAuthenticationFailureHandler customAuthenticationFailureHandler;

    @Autowired
    WeiBoLoginSuccessHandler weiBoLoginSuccessHandler;

    @Autowired
    private CiipUserService userService;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        WeiBoAuthenticationFilter weiBoAuthenticationFilter = new WeiBoAuthenticationFilter();
        weiBoAuthenticationFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
        weiBoAuthenticationFilter.setAuthenticationSuccessHandler(weiBoLoginSuccessHandler);
        weiBoAuthenticationFilter.setAuthenticationFailureHandler(customAuthenticationFailureHandler);

        WeiBoAuthenticationProvider weiBoAuthenticationProvider = new WeiBoAuthenticationProvider();
        weiBoAuthenticationProvider.setUserService(userService);

        http.authenticationProvider(weiBoAuthenticationProvider)
                .addFilterAfter(weiBoAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

    }
}

8.微博身份验证筛选器:(验证是否通过)

package com.ciip.cloud.core.usercenter.oauth.weiBo;

import com.ciip.cloud.core.common.constant.usercenter.AddableHttpRequest;
import com.ciip.cloud.core.common.constant.usercenter.CIIPCommonConstant;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

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

/**
 * Title: WeiBoAuthenticationFilter
 * Description: TODO
 *
 * @author 
 * @created 2019-05-23
 */
public class WeiBoAuthenticationFilter extends AbstractAuthenticationProcessingFilter{

    private boolean postOnly = true;
    public WeiBoAuthenticationFilter() {
        super(new AntPathRequestMatcher(CIIPCommonConstant.OAUTH_LOGIN_URL.WEIBO_LOGIN, HttpMethod.POST.name()));
    }

    public Authentication attemptAuthentication(HttpServletRequest request,HttpServletResponse response) throws AuthenticationException {
        if (postOnly && !request.getMethod().equals(HttpMethod.POST.name())) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }
        //获取openId
        AddableHttpRequest addableHttpRequest = ((AddableHttpRequest) request);
        String openId = addableHttpRequest.getParameter("openId");
        //进行登录认证
        WeiBoAuthenticationToken authRequest = new WeiBoAuthenticationToken(openId);
        setDetails(request, authRequest);
        return this.getAuthenticationManager().authenticate(authRequest);
    }
    protected void setDetails(HttpServletRequest request, WeiBoAuthenticationToken authRequest) {
        authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
    }
    public void setPostOnly(boolean postOnly) {
        this.postOnly = postOnly;
    }
}

9.微博身份验证提供程序:

package com.ciip.cloud.core.usercenter.oauth.weiBo;

import com.ciip.cloud.core.usercenter.service.CiipUserService;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;

/**
 * Title: WeiBoAuthenticationProvider
 * Description: TODO
 *
 * @author 
 * @created 2019-05-23
 */

public class WeiBoAuthenticationProvider implements AuthenticationProvider {

    private CiipUserService userService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        WeiBoAuthenticationToken authenticationToken = (WeiBoAuthenticationToken) authentication;
        String  openId =(String) authenticationToken.getPrincipal();
        UserDetails userDetails = userService.findByWeiboId(openId);
        if (userDetails == null)
            throw new InternalAuthenticationServiceException("未找到与该微博对应的用户");
        WeiBoAuthenticationToken authenticationResult = new WeiBoAuthenticationToken(userDetails, userDetails.getAuthorities());
        authenticationResult.setDetails(authenticationToken.getDetails());
        return authenticationResult;
    }

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

    public CiipUserService getUserService() {
        return userService;
    }

    public void setUserService(CiipUserService userService) {
        this.userService = userService;
    }
}

10.微博身份验证令牌:

package com.ciip.cloud.core.usercenter.oauth.weiBo;

import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;

import java.util.Collection;

/**
 * Title: WeiBoAuthenticationToken
 * Description: TODO
 *
 * @author 
 * @created 2019-05-23
 */

public class WeiBoAuthenticationToken extends AbstractAuthenticationToken {

    private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;

    private final Object principal;

    public WeiBoAuthenticationToken(Object openId) {
        super(null);
        this.principal = openId;
        setAuthenticated(false);
    }

    public WeiBoAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {
        super(authorities);
        this.principal = principal;
        super.setAuthenticated(true);
    }

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

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

    public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
        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();
    }
}

11.微博前置过滤器:

package com.ciip.cloud.core.usercenter.oauth.weiBo;

import com.alibaba.fastjson.JSON;
import com.ciip.cloud.core.common.constant.usercenter.AddableHttpRequest;
import com.ciip.cloud.core.common.constant.usercenter.CIIPCommonConstant;
import com.ciip.cloud.core.common.vo.ResultUtil;
import com.ciip.cloud.core.common.vo.usercenter.OauthCode;
import com.ciip.cloud.core.usercenter.exception.ValidateCodeException;
import com.ciip.cloud.core.usercenter.handler.CustomAuthenticationFailureHandler;
import com.ciip.cloud.core.usercenter.model.CiipUser;
import com.ciip.cloud.core.usercenter.service.CiipUserService;
import com.ciip.cloud.core.usercenter.service.WeiBoAuthService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Title: WeiBoCodeFilter
 * Description: TODO
 *
 * @author 
 * @created 2019/5/24 9:37
 */
@Component
public class WeiBoCodeFilter extends OncePerRequestFilter {

    @Autowired
    private CustomAuthenticationFailureHandler authenticationFailureHandler;
    @Autowired
    private CiipUserService ciipUserService;
    @Autowired
    private WeiBoAuthService weiBoAuthService;

    /**
     * 过滤器
     *           2019-05-24
     *
     * @param request
     * @param response
     * @param filterChain
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String openId ="";
        if (StringUtils.equalsIgnoreCase(request.getContextPath()+ CIIPCommonConstant.OAUTH_LOGIN_URL.WEIBO_LOGIN, request.getRequestURI()) && StringUtils.equalsIgnoreCase(request.getMethod(), HttpMethod.POST.name())) {
            //1.根据code,获取openId
            String code = request.getParameter("code");
            try {
                openId = weiBoAuthService.getWeiBoAccessToken(code,response);
            } catch (Exception e) {
                e.printStackTrace();
            }
            //2.将openId放入request请求对象中
            AddableHttpRequest wrappedRequest = new AddableHttpRequest(request);
            wrappedRequest.addParameter("openId",openId);

            //3.获取当前用户【登录用户】
            CiipUser ciipUser = ciipUserService.getCurrent();

            //4.不为空,表示为登录状态,用于绑定用户
             if(null != ciipUser && ("".equals(ciipUser.getWeiboId()) || null == ciipUser.getWeiboId())){

                 //5.绑定前验证,根据openId,获取对象【防止一个微博绑定多个用户】
                 CiipUser ciipUserInfo = ciipUserService.findCiipUserByWeiboId(openId);

                 //不为空,表示该微信号已经绑定其他用户
                 if(null != ciipUserInfo){
                     response.sendRedirect(thirdLoginConstants.getUrl()+"/account/binding?status=false&name=weibo");
                     return;
                 }

                 ciipUser.setWeiboId(openId);
                 ciipUserService.addCiipUser(ciipUser);
                 //添加系统消息--微博绑定成功      
                 CiipUserMessage ciipUserMessage = new CiipUserMessage();
                 Map<String,Object> paramsMap = new HashMap<String, Object>();
                 ciipUserMessage.setCreateDate(new Date());
                 ciipUserMessage.setSoruceId(ciipUser.getId());
                 ciipUserMessage.setCreateUserId(ciipUser.getId());
                 ciipUserMessage.setCreateUserName(ciipUser.getUsername());
                 ciipUserMessage.setReceiveUserId(ciipUser.getId());
                 ciipUserMessage.setMessageBusinessType(CiipMessageBusinessType.BINDING_WEIBO);
                 ciipUserMessage.setMessageType(CiipMessageType.SYSTEM);
                 ciipUserMessage.setMsgTitle("微博绑定成功");
                 ciipUserMessage.setMsgBody(StrUtil.format(CiipUserMessageTemplate.getOperationInfo(16),paramsMap));
                 ciipUserMessageService.addMessage(ciipUserMessage);

                 response.setHeader("Content-Type", "application/json;charset=UTF-8");
                 response.sendRedirect(thirdLoginConstants.getUrl()+"/account/binding");

                 //byte[] bytes = JSON.toJSONBytes(ResultUtil.error(OauthCode.BINDING_SUCCESS.getCode(), OauthCode.BINDING_SUCCESS.getMsg(), request.getHeader("referer")));
                 //response.getOutputStream().write(bytes);
                 return;
             }else{
                 //为空,表示未登录,则登录前进行验证
                 try {
                     validateWeiBoCode(openId);
                 } catch (ValidateCodeException e) {
                     wrappedRequest.addParameter("type","weiboId");
                     authenticationFailureHandler.onAuthenticationFailure(wrappedRequest, response, e);
                     return;
                 }
             }
            filterChain.doFilter(wrappedRequest, response);
        }else{
            filterChain.doFilter(request,response);
        }
       
    }

    private void validateWeiBoCode(String openId) throws ServletRequestBindingException, ValidateCodeException {
        //根据openId,获取用户信息
        UserDetails userDetails = ciipUserService.findByWeiboId(openId);
        //表示该用户不存在,跳转到注册页面
        if(null == userDetails){
            throw new ValidateCodeException("该用户与微博没有绑定或该用户不存在.");
        }
        //登录成功后,修改上次登录时间 
        CiipUser ciipUser = ciipUserService.findCiipUserByWeiboId(openId);
        if(ciipUser != null){
            if(null != ciipUser.getLoginDate() && !"".equals(ciipUser.getLoginDate())){
                ciipUser.setLastLoggedDate(ciipUser.getLoginDate());
            }else{
                ciipUser.setLastLoggedDate(new Date());
            }
            ciipUser.setLoginDate(new Date());
            ciipUserRepository.saveAndFlush(ciipUser);
        }
    }
}

12.HttpServletRequestWrapper的封装,用户request中添加参数

package com.ciip.cloud.core.common.constant.usercenter;
/**
 * Title: AddableHttpRequest
 * Description: TODO
 *
 * @author 
 * @created 2019/5/28 15:12
 */
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.*;
 
public class AddableHttpRequest extends HttpServletRequestWrapper {
 
    private HttpServletRequest wrapped;
 
    private Map<String, String[]> parameterMap;
 
    public AddableHttpRequest(HttpServletRequest wrapped) {
        super(wrapped);
        this.wrapped = wrapped;
    }
 
    public void addParameter(String name, String value) {
        if (parameterMap == null) {
            parameterMap = new HashMap<String, String[]>();
            parameterMap.putAll(wrapped.getParameterMap());
        }
        String[] values = parameterMap.get(name);
        if (values == null) {
            values = new String[0];
        }
        List<String> list = new ArrayList<String>(values.length + 1);
        list.addAll(Arrays.asList(values));
        if(!"".equals(value)){
            list.add(value);
        }
        parameterMap.put(name, list.toArray(new String[0]));
    }
 
    @Override
    public String getParameter(String name) {
        if (parameterMap == null) {
            return wrapped.getParameter(name);
        }
 
        String[] strings = parameterMap.get(name);
        if (strings != null) {
            return strings[0];
        }
        return null;
    }
 
    @Override
    public Map<String, String[]> getParameterMap() {
        if (parameterMap == null) {
            return wrapped.getParameterMap();
        }
 
        return Collections.unmodifiableMap(parameterMap);
    }
 
    @Override
    public Enumeration<String> getParameterNames() {
        if (parameterMap == null) {
            return wrapped.getParameterNames();
        }
 
        return Collections.enumeration(parameterMap.keySet());
    }
 
    @Override
    public String[] getParameterValues(String name) {
        if (parameterMap == null) {
            return wrapped.getParameterValues(name);
        }
        return parameterMap.get(name);
    }
}

13.微博登录成功处理程序:

package com.ciip.cloud.core.usercenter.oauth.weiBo;

import cn.hutool.core.lang.Console;
import cn.hutool.core.map.MapUtil;
import com.ciip.cloud.core.common.constant.enums.usercenter.CiipOperationMethod;
import com.ciip.cloud.core.common.constant.enums.usercenter.CiipOperationRecordType;
import com.ciip.cloud.core.common.constant.usercenter.CIIPCommonConstant;
import com.ciip.cloud.core.common.vo.ResultUtil;
import com.ciip.cloud.core.common.vo.usercenter.OauthCode;
import com.ciip.cloud.core.usercenter.service.CiipUserOperationLogService;
import com.ciip.cloud.core.usercenter.service.CiipUserService;
import com.ciip.cloud.core.usercenter.vo.CiipUserInfo;
import com.ciip.cloud.core.usercenter.vo.UserInfo;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Title: WeiBoLoginSuccessHandler
 * Description: TODO
 *
 * @author
 * @created 2019/5/8 18:01
 */
@Component
public class WeiBoLoginSuccessHandler implements AuthenticationSuccessHandler {

    @Autowired
    private ClientDetailsService clientDetailsService;
    @Autowired
    private AuthorizationServerTokenServices authorizationServerTokenServices;

    @Autowired
    private CiipUserOperationLogService ciipUserOperationLogService;

    private String redirectUrl ="/";

    @Autowired
    private CiipUserService ciipUserService;
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
        try {
            String clientId =  request.getParameter("clientId");
            ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
            TokenRequest tokenRequest = new TokenRequest(MapUtil.newHashMap(), clientId, clientDetails.getScope(), "mobile");
            OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);

            OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
            OAuth2AccessToken oAuth2AccessToken = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);

            Console.log("获取token 成功:{}", oAuth2AccessToken.getValue());

            UserInfo user =(UserInfo)authentication.getPrincipal();
            CiipUserInfo ciipUserInfo =  ciipUserService.getAuthUserInfo(Long.valueOf(user.getUserId()));

            //用户日志添加操作记录  
            Map<String,Object> paramsMap = new HashMap<String,Object>();
            paramsMap.put("currentUser", user.getUsername());
            ciipUserOperationLogService.addUserOperationLog(Long.valueOf(user.getUserId()),String.valueOf(user.getUserId()), CiipOperationRecordType.WEB_LOGIN.name(), CiipOperationMethod.WEIBO_LOGIN.name(), 14,paramsMap);


            //添加header认证信息
            response.setHeader(CIIPCommonConstant.AUTHORIZATION_HEADER, String.format("%s %s", CIIPCommonConstant.BEARER_TOKEN_TYPE,  oAuth2AccessToken.getValue().toString()));
            request.getSession().setAttribute(CIIPCommonConstant.BEARER_TOKEN,oAuth2AccessToken.getValue().toString());
            response.setHeader("Content-Type", "application/json;charset=UTF-8");
            //该方法为实现单点登录
            redisUtil.setWithExpireTime(CIIPCommonConstant.CIIP_AUTH,request.getSession().getId(), oAuth2AccessToken.getValue(),oAuth2AccessToken.getExpiresIn());
            //登录成功返回到首页
            response.sendRedirect(thirdLoginConstants.getUrl()+"/login");

        } catch (IOException e) {
            throw new BadCredentialsException(
                    "Failed to decode basic authentication token");
        }
    }


}

14.自定义身份验证失败处理程序:

package com.ciip.cloud.core.usercenter.handler;
 
import com.alibaba.fastjson.JSON;
import com.ciip.cloud.core.common.constant.usercenter.CIIPCommonConstant;
import com.ciip.cloud.core.common.vo.ResultUtil;
import com.ciip.cloud.core.common.vo.usercenter.OauthCode;
import com.ciip.cloud.core.usercenter.service.CiipLoginHistoryService;
import com.ciip.cloud.core.usercenter.service.CiipUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.stereotype.Component;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
 
@Component
public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
    private Logger log = LoggerFactory.getLogger(this.getClass());
    private String failureUrl = "/signIn";
 
    @Autowired
    CiipUserService ciipUserService;
    @Autowired
    CiipLoginHistoryService ciipLoginHistoryService;
 
    @Override
    public void onAuthenticationFailure(HttpServletRequest request,HttpServletResponse response, AuthenticationException exception) throws IOException {
       AddableHttpRequest addableHttpRequest = ((AddableHttpRequest) request);
            String openId = addableHttpRequest.getParameter("openId");
            String type = addableHttpRequest.getParameter("type");
            response.setHeader("Content-Type", "application/json;charset=UTF-8");
            log.info("--------------未绑定,经跳转到注册页面--------------");
            log.info("--------------openId--------------"+openId);
            log.info("--------------type--------------"+type);
            //跳转到注册页面,并带openId参数用于注册时直接绑定微信账号,type参数是微信,QQ,微博类型
            response.sendRedirect(thirdLoginConstants.getUrl()+"/register?id="+ EncryptUtil.encrypt(openId)+"&type="+type);
            //byte[] bytes = JSON.toJSONBytes(ResultUtil.error(OauthCode.USERCENTER_OAUTH_LOGIN_ERROR.getCode(),OauthCode.USERCENTER_OAUTH_LOGIN_ERROR.getMsg()+""+exception.getMessage(), "/register?"+type+"="+ EncryptUtil.encrypt(openId)));//返回到注册页面
            //response.getOutputStream().write(bytes);
    }
}

15.验证异常:

package com.ciip.cloud.core.usercenter.exception;
 
import org.springframework.security.core.AuthenticationException;
 
/**
 * Title: ValidateCodeException
 * Description: TODO
 *
 * @author 
 * @created 2019/5/8 18:33
 */
 
public class ValidateCodeException extends AuthenticationException {
 
 
    public ValidateCodeException(String message) {
        super(message);
    }
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当用户使用新浪微博进行第三方登录时,需要进行步骤: 1. 注册开发者账号:首先,你需要在新浪微博开放平台注册一个开发者账号,并创建一个应用。 2. 获取App Key和App Secret:在创建应用后,你将获得一个App Key和一个App Secret,这是用于进行身份验证和授权的凭证。 3. 引入SDK:你需要下载并引入新浪微博SDK到你的项目中。SDK提供了一些API和工具,方便你与新浪微博进行交互。 4. 授权登录:在你的应用中,提供一个登录按钮或者其他触发登录的方式。当用户点击登录按钮时,调用新浪微博SDK提供的接口,请求用户授权登录。 5. 获取Access Token:在用户授权登录成功后,你将获得一个Access Token。这个Token可以用来访问用户的个人信息和进行其他操作。 6. 调用API:使用获得的Access Token,你可以调用新浪微博提供的API来获取用户信息、发布微博等操作。 下面是一个简单的示例代码,展示了如何使用新浪微博SDK进行第三方登录: ```java // 引入SDK import com.sina.weibo.sdk.auth.Oauth2AccessToken; import com.sina.weibo.sdk.auth.WbConnectErrorMessage; import com.sina.weibo.sdk.auth.WbConnectObserver; import com.sina.weibo.sdk.auth.WbConnectProgressDialog; import com.sina.weibo.sdk.auth.sso.SsoHandler; import com.sina.weibo.sdk.common.UiError; import com.sina.weibo.sdk.share.WbShareCallback; import com.sina.weibo.sdk.share.WbShareHandler; // 创建SsoHandler对象 private SsoHandler mSsoHandler; // 在登录按钮的点击事件中调用以下代码 mSsoHandler = new SsoHandler(MainActivity.this); mSsoHandler.authorize(new WbConnectObserver() { @Override public void onSuccess(Oauth2AccessToken oauth2AccessToken) { // 登录成功,获取Access Token String accessToken = oauth2AccessToken.getToken(); // TODO: 进行后续操作,如获取用户信息等 } @Override public void onFailure(WbConnectErrorMessage wbConnectErrorMessage) { // 登录失败,处理错误信息 String errorMessage = wbConnectErrorMessage.getErrorMessage(); // TODO: 处理登录失败的情况 } }); // 在Activity的onActivityResult方法中添加以下代码 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (mSsoHandler != null) { mSsoHandler.authorizeCallBack(requestCode, resultCode, data); } } ``` 请注意,以上代码仅为示例,实际使用时需要根据你的项目需求进行适当修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值