当前位置: 首页 > news >正文

企业做网站优点/网络营销师工作内容

企业做网站优点,网络营销师工作内容,WordPress建站主机推荐,网站目录文件夹1. 前言 在之前的Spring Social系列中,我们只是实现了使用服务提供商账号登录到业务系统中,但没有与业务系统中的账号进行关联。本章承接之前社交系列来实现社交账号与业务系统账号的绑定与解绑。 Spring-Security源码分析三-Spring-Social社交登录过程…

1. 前言

在之前的Spring Social系列中,我们只是实现了使用服务提供商账号登录到业务系统中,但没有与业务系统中的账号进行关联。本章承接之前社交系列来实现社交账号与业务系统账号的绑定与解绑。

  1. Spring-Security源码分析三-Spring-Social社交登录过程
  2. Spring-Security源码分析四-Spring-Social社交登录过程
  3. Spring-Security源码分析六-Spring-Social社交登录源码解析

1.1 UserConnection

create table UserConnection (userId varchar(255) not null,providerId varchar(255) not null,providerUserId varchar(255),......primary key (userId, providerId, providerUserId));
create unique index UserConnectionRank on UserConnection(userId, providerId, rank);

在使用社交登录的时我们创建的UserConnection表,下面我们来简单分析一下

  1. userId业务系统的用户唯一标识(我们使用的是username
  2. providerId用于区分不同的服务提供商(qq,weixin,weibo
  3. providerUserId 服务提供商返回的唯一标识(openid

1.2 社交登录注册实现

1.2.1 取消MyConnectionSignUp

在Spring-Security源码分析六-Spring-Social社交登录源码解析中,我们得知,当配置ConnectionSignUp时,Spring Social会根据我们配置的MyConnectionSignUp返回userId,接着执行userDetailsService.loadUserByUserId(userId),实现社交账号登录。当取消掉MyConnectionSignUp则会抛出BadCredentialsException,BadCredentialsException由SocialAuthenticationFilter处理,跳转到默认的/signup注册请求,跳转之前会将当前的社交账号信息保存到session中。

1.2.1.1 添加自定义注册请求/socialRegister

@Overrideprotected <T> T postProcess(T object) {SocialAuthenticationFilter filter = (SocialAuthenticationFilter) super.postProcess(object);filter.setFilterProcessesUrl(filterProcessesUrl);filter.setSignupUrl("/socialRegister");return (T) filter;}

1.2.1.2 添加到.permitAll(); 

.authorizeRequests().antMatchers(SecurityConstants.DEFAULT_UNAUTHENTICATION_URL,......"/socialRegister",//社交账号注册和绑定页面"/user/register",//处理社交注册请求.......permitAll()//以上的请求都不需要认证

1.2.3 配置ProviderSignInUtils

从Session中获取社交账号信息

@Beanpublic ProviderSignInUtils providerSignInUtils(ConnectionFactoryLocator factoryLocator) {return new ProviderSignInUtils(factoryLocator, getUsersConnectionRepository(factoryLocator));}

1.2.4 创建SocialUserInfo

展示当前社交账号信息

@Datapublic class SocialUserInfo {private String providerId;private String providerUserId;private String nickname;private String headImg;}

1.2.5 实现socialRegister和user/register

1.2.5.1 /socialRegister

@GetMapping(value = "/socialRegister")public ModelAndView socialRegister(HttpServletRequest request, Map<String, Object> map) {SocialUserInfo userInfo = new SocialUserInfo();Connection<?> connection = providerSignInUtils.getConnectionFromSession(new ServletWebRequest(request));userInfo.setProviderId(connection.getKey().getProviderId());//哪一个服务提供商userInfo.setProviderUserId(connection.getKey().getProviderUserId());//openiduserInfo.setNickname(connection.getDisplayName());//名称userInfo.setHeadImg(connection.getImageUrl());//显示头像map.put("user", userInfo);return new ModelAndView("socialRegister", map);}

1.2.5.2 /user/register 

@PostMapping("/user/register")public String register(SysUser user, HttpServletRequest request, HttpServletResponse response) throws IOException {String userId = user.getUsername();//获取用户名SysUser result =  sysUserService.findByUsername(userId);//根据用户名查询用户信息if(result==null){//如果为空则注册用户sysUserService.save(user);}//将业务系统的用户与社交用户绑定providerSignInUtils.doPostSignUp(userId, new ServletWebRequest(request));//跳转到indexreturn "redirect:/index";}

1.2.6 修改MyUserDetailsService#loadUserByUserId 

@Override
public SocialUserDetails loadUserByUserId(String userId) throws UsernameNotFoundException {SysUser user = repository.findByUsername(userId);//根据用户名查找用户return user;
}

效果如下: 注册效果如下:

1.3 绑定与解绑实现

要实现绑定与解绑,首先我们需要知道社交账号的绑定状态,绑定就是重新走一下OAuth2流程,关联当前登录用户,解绑就是删除UserConnection表数据。Spring Social默认在ConnectController类上已经帮我们实现了以上的需求。

1.3.1 获取状态

/connect获取状态。

@RequestMapping(method=RequestMethod.GET)public String connectionStatus(NativeWebRequest request, Model model) {setNoCache(request);processFlash(request, model);Map<String, List<Connection<?>>> connections = connectionRepository.findAllConnections();//根据userId查询UserConnection表model.addAttribute("providerIds", connectionFactoryLocator.registeredProviderIds());//系统中已经注册的服务提供商		model.addAttribute("connectionMap", connections);return connectView();//返回connectView()}protected String connectView() {return getViewPath() + "status";//connect/status }

由以上可得,实现connect/status视图即可获得社交账号的绑定状态。

1.3.1.1 实现connect/status

@Component("connect/status")
public class SocialConnectionStatusView extends AbstractView {@Autowiredprivate ObjectMapper objectMapper;@Overrideprotected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {Map<String, List<Connection<?>>> connections = (Map<String, List<Connection<?>>>) model.get("connectionMap");Map<String, Boolean> result = new HashMap<>();for (String key : connections.keySet()) {result.put(key, CollectionUtils.isNotEmpty(connections.get(key)));}response.setContentType("application/json;charset=UTF-8");response.getWriter().write(objectMapper.writeValueAsString(ResultUtil.success(result)));}
}

返回结果如下:https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/security/spring-social-status.png

1.3.2 绑定的实现

/connect/{providerId}绑定社交账号(POST请求)

跳转到授权的页面
@RequestMapping(value="/{providerId}", method=RequestMethod.POST)public RedirectView connect(@PathVariable String providerId, NativeWebRequest request) {ConnectionFactory<?> connectionFactory = connectionFactoryLocator.getConnectionFactory(providerId);MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>(); preConnect(connectionFactory, parameters, request);try {return new RedirectView(connectSupport.buildOAuthUrl(connectionFactory, request, parameters));} catch (Exception e) {sessionStrategy.setAttribute(request, PROVIDER_ERROR_ATTRIBUTE, e);return connectionStatusRedirect(providerId, request);}}

授权成功的回调地址 

//将当前的登录账户与社交账号绑定(写入到UserConnection表)
@RequestMapping(value="/{providerId}", method=RequestMethod.GET, params="code")public RedirectView oauth2Callback(@PathVariable String providerId, NativeWebRequest request) {try {OAuth2ConnectionFactory<?> connectionFactory = (OAuth2ConnectionFactory<?>) connectionFactoryLocator.getConnectionFactory(providerId);Connection<?> connection = connectSupport.completeConnection(connectionFactory, request);addConnection(connection, connectionFactory, request);} catch (Exception e) {sessionStrategy.setAttribute(request, PROVIDER_ERROR_ATTRIBUTE, e);logger.warn("Exception while handling OAuth2 callback (" + e.getMessage() + "). Redirecting to " + providerId +" connection status page.");}return connectionStatusRedirect(providerId, request);}//返回/connext/qqed视图protected RedirectView connectionStatusRedirect(String providerId, NativeWebRequest request) {HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);String path = "/connect/" + providerId + getPathExtension(servletRequest);if (prependServletPath(servletRequest)) {path = servletRequest.getServletPath() + path;}return new RedirectView(path, true);}

1.3.2.1 实现 connect/qqConnected视图 

@Bean("connect/qqConnected")public View qqConnectedView() {return new SocialConnectView();}public class SocialConnectView extends AbstractView {@Overrideprotected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {String msg = "";response.setContentType("text/html;charset=UTF-8");if (model.get("connections") == null) {msg = "unBindingSuccess";
//            response.getWriter().write("<h3>解绑成功</h3>");} else {msg = "bindingSuccess";
//            response.getWriter().write("<h3>绑定成功</h3>");}response.sendRedirect("/message/" + msg);}
}

效果如下:

1.3.3 解绑的实现

/connect/{providerId}绑定社交账号(DELETE请求)

//删除UserConnection表数据,返回connect/qqConnect视图
@RequestMapping(value="/{providerId}", method=RequestMethod.DELETE)public RedirectView removeConnections(@PathVariable String providerId, NativeWebRequest request) {ConnectionFactory<?> connectionFactory = connectionFactoryLocator.getConnectionFactory(providerId);preDisconnect(connectionFactory, request);connectionRepository.removeConnections(providerId);postDisconnect(connectionFactory, request);return connectionStatusRedirect(providerId, request);}

1.3.3.1 实现connect/qqConnect视图 

/*** /connect/qq POST请求,绑定微信返回connect/qqConnected视图* /connect/qq DELETE请求,解绑返回connect/qqConnect视图* @return*/@Bean({"connect/qqConnect", "connect/qqConnected"})@ConditionalOnMissingBean(name = "qqConnectedView")public View qqConnectedView() {return new SocialConnectView();}

效果如下:

2. 代码下载

从我的 github 中下载,https://github.com/longfeizheng/logback

http://www.lbrq.cn/news/1768915.html

相关文章:

  • 网站建设需要具备哪些知识/友情链接的四个技巧
  • 怎么看网站是什么语言做的后台/泉州百度搜索推广
  • 阿里建设网站/深圳做网站公司哪家好
  • 福州餐饮网站建设/小广告怎么能弄干净
  • html5网页素材/网站搜索优化价格
  • 北京公司网站建设费用/竞价培训课程
  • 网站后台管理系统如何安装/怎么推广产品
  • wordpress 生成 应用/驻马店百度seo
  • wordpress 页脚广告/软件网站关键词优化
  • 网站做任务给钱的/地推的60种方法
  • 凡科建站代理商登录/苏州seo怎么做
  • 个人做网站需要什么资料/永久免费跨境浏览app
  • 制作app的网站/广告优化师怎么学
  • 自己怎么开网站做销售/微信引流推广怎么做
  • 价格划算的做网站/跨境电商seo
  • 网页设计与网站建设在线考试1/关键词搜索引擎排名查询
  • 网站域名和空间费用/新的网络推广方式
  • 做行政关注什么类型的网站/网站友链外链
  • 网站程序更换/seo常用分析的专业工具
  • 绵阳网站建设100jv/网站子域名查询
  • 海口公司做网站/2023年的新闻时事热点论文
  • 摄影工作室网站设计/站长统计网站
  • 珠海东莞网站建设/买卖链接网站
  • 做推广都有什么网站/上海正规seo公司
  • 现在的网站是用什么软件做的/百度快速收录
  • 网站开发音乐/网站百度收录查询
  • 动态网站背景做多少合适/广告接单平台有哪些
  • 香山红叶建设有限公司网站/开网店哪个平台靠谱
  • 网站建设成都/百度竞价查询
  • 深圳做网站 信科便宜/资源网站优化排名软件公司
  • AI问答-Token:在人工智能领域,Token 是模型处理文本的核心单元 / 最小可处理片段
  • [AI-video] Web UI | Streamlit(py to web) | 应用配置config.toml
  • 春秋云镜 initial
  • 设备发出、接收数据帧的工作机制
  • 设计模式(行为型)-迭代器模式
  • 嵌入式硬件篇---晶体管的分类