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

怎样办网站网络营销的六大特征

怎样办网站,网络营销的六大特征,用iis为公司做一个内部网站,网站建设版面分几页合适MFA多因素认证(Multi-Factor Authentication ): 一些需要身份认证的服务(如网站),为了提升安全性,通常会在账号密码登录成功后,要求用户进行第二种身份认证,以确保是正确用户登录,避…

MFA多因素认证(Multi-Factor Authentication ):
一些需要身份认证的服务(如网站),为了提升安全性,通常会在账号密码登录成功后,要求用户进行第二种身份认证,以确保是正确用户登录,避免用户密码泄露了或其它原因导致用户信息泄露。
不过,用户体验就比较差,因为要登录2次嘛。
常见使用场景:

  • 企业的管理后台,尤其是涉及敏感信息的系统,比如CMS客户关系管理系统、财务系统等
  • 电商后台,比如亚马逊店铺管理后台,通常都要二次认证
  • Git代码仓库
  • 站点上用户敏感信息的查看、修改,如手机号默认隐藏中间n位,要查看必须二次认证;修改密码要二次认证等

常见的认证方式有:

  • 手机短信验证码验证:把验证码通过短信发给用户,用户在该服务里(如网站)上输入该验证码并认证
  • 邮箱验证码验证:把验证码通过邮件发给用户,用户输入该验证码并认证
  • MFA硬件设备:给用户分配一个硬件设施,用于生成动态口令,用户输入该口令并认证
    还有一种硬件设备是插入电脑即可自动认证
  • MFA软件:用户在电脑或手机上安装一个软件,软件里生成动态口令,用户输入该口令并认证
  • 生物识别:通过指纹、人脸识别等生物特征进行认证
  • 智能卡:给用户分配一张带身份信息的卡片,用户把卡片放在服务的读卡设备上进行认证

本文只介绍网站的MFA软件接入方案,并采用手机应用进行认证。
只要是基于时间同步算法的手机应用,都可以支持,如以下应用:

  • 谷歌身份验证器(google authenticator)
  • 微软身份验证器(Microsoft Authenticator)
    注:这种动态口令认证,通常也称之为OTP-Code(One-time Password)、OTP令牌、两步验证、二次认证、2FA等。

前端与后端的交互流程如下:

后端提供3个接口:

  • 账号密码登录接口
  • 该账号是否绑定过SecureKey的接口
  • 二次验证码校验接口

完整交互流程图参考如下:
在这里插入图片描述

SpringBoot项目接入实现

假设已经创建了SpringBoot项目。

添加依赖

打开pom.xml文件,添加如下依赖:

<!-- 用于SecureKey生成 -->
<dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId>
</dependency><!-- 用于二维码生成 -->
<dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version>
</dependency>
<dependency><groupId>com.google.zxing</groupId><artifactId>javase</artifactId><version>3.5.1</version>
</dependency>

SecureKey生成与验证码生成比对类

这个是核心实现类,主要功能:

  • 生成随机的SecureKey,用于外部业务绑定到指定账号,也用于后续的验证码生成
  • 根据SecureKey和系统时间,生成相应的验证码

代码参考:

package beinet.cn.googleauthenticatordemo.authenticator;import org.apache.commons.codec.binary.Base32;import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;public class GoogleGenerator {// 发行者(项目名),可为空,注:不允许包含冒号public static final String ISSUER = "beinet.cn";// 生成的key长度( Generate secret key length)public static final int SECRET_SIZE = 32;// Java实现随机数算法public static final String RANDOM_NUMBER_ALGORITHM = "SHA1PRNG";// 最多可偏移的时间, 假设为2,表示计算前面2次、当前时间、后面2次,共5个时间内的验证码static int window_size = 1; // max 17static long second_per_size = 30L;// 每次时间长度,默认30秒/*** 生成一个SecretKey,外部绑定到用户** @return SecretKey*/public static String generateSecretKey() {SecureRandom sr;try {sr = SecureRandom.getInstance(RANDOM_NUMBER_ALGORITHM);sr.setSeed(getSeed());byte[] buffer = sr.generateSeed(SECRET_SIZE);Base32 codec = new Base32();byte[] bEncodedKey = codec.encode(buffer);String ret = new String(bEncodedKey);return ret.replaceAll("=+$", "");// 移除末尾的等号} catch (NoSuchAlgorithmException e) {// should never occur... configuration errorthrow new RuntimeException(e);}}/*** 生成二维码所需的字符串,注:这个format不可修改,否则会导致身份验证器无法识别二维码** @param user   绑定到的用户名* @param secret 对应的secretKey* @return 二维码字符串*/public static String getQRBarcode(String user, String secret) {if (ISSUER != null) {if (ISSUER.contains(":")) {throw new IllegalArgumentException("Issuer cannot contain the ':' character.");}user = ISSUER + ":" + user;}String format = "otpauth://totp/%s?secret=%s";String ret = String.format(format, user, secret);if (ISSUER != null) {ret += "&issuer=" + ISSUER;}return ret;}/*** 验证用户提交的code是否匹配** @param secret 用户绑定的secretKey* @param code   用户输入的code* @return 匹配成功与否*/public static boolean checkCode(String secret, int code) {Base32 codec = new Base32();byte[] decodedKey = codec.decode(secret);// convert unix msec time into a 30 second "window"// this is per the TOTP spec (see the RFC for details)long timeMsec = System.currentTimeMillis();long t = (timeMsec / 1000L) / second_per_size;// Window is used to check codes generated in the near past.// You can use this value to tune how far you're willing to go.for (int i = -window_size; i <= window_size; ++i) {int hash;try {hash = verifyCode(decodedKey, t + i);} catch (Exception e) {// Yes, this is bad form - but// the exceptions thrown would be rare and a static// configuration probleme.printStackTrace();throw new RuntimeException(e.getMessage());// return false;}System.out.println("input code=" + code + "; count hash=" + hash);if (code == hash) { // addZero(hash)return true;}
/*            if (code==hash ) {return true;}*/}// The validation code is invalid.return false;}private static int verifyCode(byte[] key, long t) throws NoSuchAlgorithmException, InvalidKeyException {byte[] data = new byte[8];long value = t;for (int i = 8; i-- > 0; value >>>= 8) {data[i] = (byte) value;}SecretKeySpec signKey = new SecretKeySpec(key, "HmacSHA1");Mac mac = Mac.getInstance("HmacSHA1");mac.init(signKey);byte[] hash = mac.doFinal(data);int offset = hash[20 - 1] & 0xF;// We're using a long because Java hasn't got unsigned int.long truncatedHash = 0;for (int i = 0; i < 4; ++i) {truncatedHash <<= 8;// We are dealing with signed bytes:// we just keep the first byte.truncatedHash |= (hash[offset + i] & 0xFF);}truncatedHash &= 0x7FFFFFFF;truncatedHash %= 1000000;return (int) truncatedHash;}private static byte[] getSeed() {String str = ISSUER + System.currentTimeMillis() + ISSUER;return str.getBytes(StandardCharsets.UTF_8);}
}

业务服务类实现

用于封装2个方法:

  • 输入账号,为该账号生成并绑定SecureKey入库,同时返回谷歌身份验证器所需的二维码URL
  • 输入账号和验证码,获取该账号对应的SecureKey,并计算当前时间的验证码,与输入的验证码进行比对,返回成功与否

参考实现:

package beinet.cn.googleauthenticatordemo.authenticator;import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;import java.util.HashMap;
import java.util.Map;@Service
public class AuthenticatorService {private Map<String, String> userKeys = new HashMap<>();/*** 生成一个secretKey,并关联到用户,* 然后返回二维码字符串** @param username 用户名* @return 二维码字符串*/public String generateAuthUrl(String username) {String secret = GoogleGenerator.generateSecretKey();// todo: 实际项目中,用户名与secretKey的关联关系应当存储在数据库里,否则变化了,就会无法登录userKeys.put(username, secret);return GoogleGenerator.getQRBarcode(username, secret);}/*** 根据用户名和输入的code,进行校验并返回成功失败** @param username 用户名* @param code     输入的code* @return 校验成功与否*/public boolean validateCode(String username, int code) {// todo: 从数据库里读取该用户的secretKeyString secret = userKeys.get(username);if (!StringUtils.hasLength(secret)) {throw new RuntimeException("该用户未使用Google身份验证器注册,请先注册");}return GoogleGenerator.checkCode(secret, code);}
}

登录流程嵌入

这个根据实际代码进行修改,比如前后端分离的项目:

  • 前端页面在登录成功时,增加代码:
    • 判断当前用户是否绑定过,未绑定时,显示二维码让用户绑定
    • 弹出OTPCode输入界面,二次验证成功再跳转正常业务页
  • 后端业务接口,需要判断2个Cookie都存在时才进入,少一个都要返回登录失败

完整Demo代码

  • 使用上面的代码实现的,带登录+二次验证的完整代码参考:
    https://github.com/youbl/study/tree/master/study-codes/google-authenticator-demo
    可以查看该目录的历史提交记录,了解每个步骤做了哪些动作

手机应用下载

Google Authenticator下载

使用比较简单,手机上无需登录,可直接打开。

  • 苹果版本下载地址:
    https://apps.apple.com/cn/app/google-authenticator/id388497605
  • 安卓版本下载地址:
    https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en_US
  • 国内无法访问谷歌市场的,可以去这里下载apk安装:
    https://apkpure.com/cn/google-authenticator/com.google.android.apps.authenticator2

Microsoft Authenticator下载

有一定安全性,需要进行密码或指纹验证,才能打开。

  • 苹果版本下载地址:
    https://apps.apple.com/us/app/microsoft-authenticator/id983156458
  • 安卓版本下载地址:
    https://play.google.com/store/apps/details?id=com.azure.authenticator&hl=en_US
  • 国内无法访问谷歌市场的,可以去这里下载apk安装:
    https://apkpure.com/cn/microsoft-authenticator/com.azure.authenticator
http://www.ds6.com.cn/news/67025.html

相关文章:

  • 太原制作网站的公司哪家好怎样申请网站
  • 电子商务平台(网站)建设方式百度seo引流怎么做
  • 秦皇岛做网站优化网络营销的工具和方法
  • 修改网站后台地址公司网站
  • 企业网站建设管理平台外链下载
  • 中文电子商务网站模板互联网销售模式
  • 购物网站的设计思路如何创建网站教程
  • 江西省网站开发盐城seo排名
  • 公司网站模块制作网站建设费用
  • 电影网站怎么做优化网站推广途径和推广要点
  • dede 网站地图样式希爱力的作用与功效
  • 手机网站用什么域名橘子seo
  • 成都分想设计公司网站雅虎搜索
  • 网站建设都有那些费用搜索引擎查关键词排名的软件
  • 深圳网站公司招聘seo营销优化
  • 网站等保测评怎么做江苏网站推广
  • 宝安网站建设方案外包如何推广公司
  • 网站建设实训课指导书网站版式分析无代码系统搭建平台
  • 济南莱芜都市网南京百度快速排名优化
  • 免费注册b2b网站百度重庆营销中心
  • 做分享衣服网站的初衷是什么意思厦门百度推广开户
  • 在浙学网页设计与制作答案网站 seo
  • 专做外贸的网站有哪些做电商必备的几个软件
  • 哪个网站卖做阳具好点关联词有哪些 全部
  • asp网站连不上数据库网站搭建平台都有哪些
  • 番禺网站建设平台北京seo专员
  • 邢台企业做网站找谁企业营销培训课程
  • 网站改版 百度收录东莞今日新闻大事
  • 抚顺建设银行网站广州王牌seo
  • 弹幕视频网站开发优化关键词有哪些方法