精华内容
下载资源
问答
  • Java实现邮箱激活账户实例

    千次阅读 多人点赞 2017-07-24 22:39:34
    手机验证:填写手机号码,点击发送验证码,接收后填写验证码比对,无误后注册成功。 邮箱验证:注册时填写邮箱账号,点击注册,网站邮箱会给该邮箱发送一封激活邮件,用户点击后激活该账号。   这里通过实例来...

    在网站注册时一般都会要验证注册用户身份的合法性,通常的做法是提供手机号验证或者邮箱验证。

    手机验证:填写手机号码,点击发送验证码,接收后填写验证码比对,无误后注册成功。

    邮箱验证:注册时填写邮箱账号,点击注册,网站邮箱会给该邮箱发送一封激活邮件,用户点击后激活该账号。

     

    这里通过实例来介绍一下邮箱验证的实现过程,例子可以运行,暂时没有发现什么问题,不过也可能有不安全的地方,欢迎大家指正。

     

    实现思路

    注册时填写邮箱,点击注册时网站系统邮箱发送激活验证链接到此邮箱,用户来激活账户


    点击注册,系统邮箱会发送一封激活邮件到你填写的邮箱账号中

    在没有进行激活操作前,设定某个字段状态是0,表示此账号未激活,不可以使用或者某些功能受限

    激活操作之后,将activated字段更新为1,这样就完成了激活操作

    那么这里还有一个codeUrl字段,他的作用是存入一个唯一标识的随机码,这个随机码由用户名和UUID唯一标识的随机数组成,这样做的目的是防止用户使用不存在的邮箱又修改链接中的参数来激活账户,将链接中的随机码和数据库中的比对,来达到相对安全的激活。

     

    下面是具体的代码

    首先是注册的servlet,这里主要测试激活账号的功能,注册代码有点low,不安全,将就看一下

    package org.amuxia.emailtest.servlet;
    
    import java.io.IOException;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.UUID;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.amuxia.emailtest.pojo.User;
    import org.amuxia.emailtest.utils.EmailUtils;
    import org.amuxia.emailtest.utils.MyJDBC;
    
    /**
     * @author amuxia
     * 2017年7月24日
     */
    @WebServlet("/RegistServlet")
    public class RegistServlet extends HttpServlet {  
        private static final long serialVersionUID = 1L;  
      
        protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
            String username = request.getParameter("username");  
            String password = request.getParameter("password");  
            String email = request.getParameter("email"); 
            String codeUrl = UUID.randomUUID().toString();
            User user = new User(); 
            user.setUsername(username);  
            user.setPassword(password);  
            user.setEmail(email);  
            user.setActivated(false);  //刚注册默认是没有激活状态
            String SQL = "insert into tb_user(username,password,email,activated,codeUrl) value (?,?,?,?,?) ";
            MyJDBC.insert(SQL, false, username,password,email,0,codeUrl);//注册信息插入数据库
            String querySQL = "select * from tb_user where email=?";
            ResultSet rs = MyJDBC.query(querySQL, email);
            try {
    			if(rs.next()){
    				user.setId(rs.getInt(1));
    			}
    		} catch (SQLException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
            
            // 注册成功后,发送帐户激活链接  
            request.getSession().setAttribute("user", user); 
            EmailUtils.sendAccountActivateEmail(user); 
            request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request,response);  
        }  
    
    }
    

    激活账号的Servlet,也就是更新操作

    package org.amuxia.emailtest.servlet;
    
    import java.io.IOException;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.amuxia.emailtest.pojo.User;
    import org.amuxia.emailtest.utils.GenerateLinkUtils;
    import org.amuxia.emailtest.utils.MyJDBC;
    
    /**
     * @author amuxia
     * 2017年7月24日
     */
    @WebServlet("/ActivateServlet")
    public class ActivateServlet extends HttpServlet{
    	private static final long serialVersionUID = 1L;
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) 
    		throws ServletException, IOException {
    	// TODO Auto-generated method stub
    	String idValue = request.getParameter("id");
    	System.out.println(idValue);
    	int id = -1;
    	try {
    		id = Integer.parseInt(idValue);
    	} catch (NumberFormatException e) {
    		e.printStackTrace();
    	}
    	String SQL = "select * from tb_user where id=?";
    	ResultSet rs= MyJDBC.query(SQL, id);
    	User user = new User();
    	try {
    		if(rs.next()){
    			user.setId(rs.getInt(1));
    			user.setUsername(rs.getString(2));
    			user.setPassword(rs.getString(3));
    			user.setEmail(rs.getString(4));
    			user.setActivated(rs.getBoolean(5));
    			user.setCodeUrl(rs.getString(6));
    		}
    	} catch (SQLException e) {
    		// TODO Auto-generated catch block
    		e.printStackTrace();
    	}
    	//验证无误,状态更改为1,即激活
    	if(GenerateLinkUtils.verifyCheckcode(user, request)){
    		String updSQL = "update tb_user set activated =1 where id=?";
    		MyJDBC.execute(updSQL, id);
    		user.setActivated(true);
    		request.getSession().setAttribute("user", user);
    		request.getRequestDispatcher("/WEB-INF/jsp/pass.jsp").forward(request, response);
    	}
    	}
    }
    

    发送Email的工具类

    package org.amuxia.emailtest.utils;
    
    import java.util.Date;
    import java.util.Properties;
    
    import javax.mail.Authenticator;
    import javax.mail.Message.RecipientType;
    import javax.mail.PasswordAuthentication;
    import javax.mail.Session;
    import javax.mail.Transport;
    import javax.mail.internet.InternetAddress;
    import javax.mail.internet.MimeMessage;
    
    import org.amuxia.emailtest.pojo.User;
    
    /**
     * @author amuxia
     * 2017年7月24日
     */
    public class EmailUtils {
    	
    	private static final String FROM = "要发送邮件的邮箱,这个例子是163邮箱";
    
    	public static void sendAccountActivateEmail(User user) {
    		Session session = getSession();
    		MimeMessage message = new MimeMessage(session);
    		try {
    			message.setSubject("这是一封激活账号的邮件,复制链接到地址栏来激活他");
    			message.setSentDate(new Date());
    			message.setFrom(new InternetAddress(FROM));
    			message.setRecipient(RecipientType.TO, new InternetAddress(user.getEmail()));
    			message.setContent("<a  target='_BLANK' href=''>"+GenerateLinkUtils.generateActivateLink(user)+"</a>","text/html;charset=utf-8");
    			Transport.send(message);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    	
    	public static Session getSession() {
    		Properties props = new Properties();
    		props.setProperty("mail.transport.protocol", "smtp");
    		props.setProperty("mail.smtp.host", "smtp.163.com");
    		props.setProperty("mail.smtp.port", "25");
    		props.setProperty("mail.smtp.auth", "true");
    		Session session = Session.getInstance(props, new Authenticator() {
    			@Override
    			protected PasswordAuthentication getPasswordAuthentication() {
    				return new PasswordAuthentication(FROM, "上面邮箱的密码");
    			}
    			
    		});
    		return session;
    	}
    }
    
    这里需要注意一下,以上例子配置的是163邮箱,需要进行邮箱客户端的授权,授权之后,网易邮箱会发来一份客户端授权码作为替代邮箱密码,代码里填写的密码其实是授权码,配置好邮箱最好发一份邮件测试一下,有时程序出问题很可能是邮箱客户端根本发不了邮件

    加密账户激活链接生成的工具类

    package org.amuxia.emailtest.utils;
    
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    
    import javax.servlet.ServletRequest;
    
    import org.amuxia.emailtest.pojo.User;
    
    /**
     * @author amuxia
     * 2017年7月24日
     */
    public class GenerateLinkUtils {
    	
    	private static final String CHECK_CODE = "checkCode";
    	
    	public static String generateActivateLink(User user) {
    		return "http://localhost/EmailDemo/ActivateServlet?id=" 
    				+ user.getId() + "&" + CHECK_CODE + "=" + generateCheckcode(user);
    	}
    	
    	
    	/**
    	 * 生成校验码,用户名+UUID唯一标识符,为安全把他们加密发送
    	 * @param user
    	 * @return
    	 */
    	public static String generateCheckcode(User user) {
    		String userName = user.getUsername();
    		String randomCode = user.getCodeUrl();
    		return md5(userName + ":" + randomCode);
    	}
    
    	
    	/**
    	 * 接收回来的校验码和发送出去的是不是同一份
    	 * @param user
    	 * @param request
    	 * @return
    	 */
    	public static boolean verifyCheckcode(User user,ServletRequest request) {
    		String checkCode = request.getParameter(CHECK_CODE);
    		System.out.println(generateCheckcode(user).equals(checkCode));
    		return true;
    	}
    
    	private static String md5(String string) {
    		MessageDigest md = null;
    		try {
    			md = MessageDigest.getInstance("md5");
    			md.update(string.getBytes());
    			byte[] md5Bytes = md.digest();
    			return bytes2Hex(md5Bytes);
    		} catch (NoSuchAlgorithmException e) {
    			e.printStackTrace();
    			System.out.println("md5这里出错了");
    		}
    		
    		return null;
    	}
    	
    	private static String bytes2Hex(byte[] byteArray)
    	{
    		StringBuffer strBuf = new StringBuffer();
    		for (int i = 0; i < byteArray.length; i++)
    		{
    			if(byteArray[i] >= 0 && byteArray[i] < 16)
    			{
    				strBuf.append("0");
    			}
    			strBuf.append(Integer.toHexString(byteArray[i] & 0xFF));
    		}
    		return strBuf.toString();
    	}
    
    }
    

    还有一个操作数据库的封装类,MyJDBC,前面博客有写,代码挺长,就不贴了,这是链接:http://blog.csdn.net/weixin_36380516/article/details/72904214

    实体类User

    package org.amuxia.emailtest.pojo;
    
    public class User {
    	private int id;
    	private String username;
    	private String password;
    	private String email;
    	private boolean activated;//账号状态
    	private String codeUrl;//激活链接中的随机码
    	
    	public int getId() {
    		return id;
    	}
    	public void setId(int id) {
    		this.id = id;
    	}
    	public String getUsername() {
    		return username;
    	}
    	public void setUsername(String username) {
    		this.username = username;
    	}
    	public String getPassword() {
    		return password;
    	}
    	public void setPassword(String password) {
    		this.password = password;
    	}
    	public String getEmail() {
    		return email;
    	}
    	public void setEmail(String email) {
    		this.email = email;
    	}
    
    	public boolean isActivated() {
    		return activated;
    	}
    	public void setActivated(boolean activated) {
    		this.activated = activated;
    	}
    	public String getCodeUrl() {
    		return codeUrl;
    	}
    	public void setCodeUrl(String codeUrl) {
    		this.codeUrl = codeUrl;
    	}
    	public User() {
    		super();
    		
    	}
    	
    }
    

    注册的jsp

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
    <head>
    
    <title>注册</title>
    </head>
    
    <body>
    	<form action="/EmailDemo/RegistServlet" method="post">
    		用户名:<input type="text" name="username"><br/>
    		密码:<input type="password" name="password"><br/>
    		邮箱:<input type="text" name="email"><br/>
    		<input type="submit" value="注册">
    	</form>
    </body>
    </html>
    
    用到的包?


    邮箱验证的大概功能就完成了,但是还有很多不足之处,貌似应该设置一个过期时间。等等。。。

    展开全文
  • 模仿一些网站在注册的时候要填写手机号码,然后点击获取激活码,将会产生一个激活码,用短信的方式发到注册者的手机,然后用户需要查看短信,将激活码填写在注册页面,有时间限制。若超时则需要重新发送。  ...

    模仿一些网站在注册的时候要填写手机号码,然后点击获取激活码,将会产生一个激活码,用短信的方式发到注册者的手机,然后用户需要查看短信,将激活码填写在注册页面,有时间限制。若超时则需要重新发送。 

    strings.xml,其代码如下:

    [html] view plaincopy
    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <resources>  
    3.   
    4.     <string name="hello">Hello World, SendregActivity!</string>  
    5.     <string name="app_name">发送验证码</string>  
    6.     <string name="title">注册</string>  
    7.     <string name="links">我已阅读并接受:<a href="http://www.baidu.com">《百度用户协议》 </a>   </string>  
    8. </resources>  
    9.    

    color.xml,其代码如下:

    [html] view plaincopy
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <resources>  
    3.    <color name="skyblue">#87CEEB</color><!--天蓝色 -->   
    4. </resources>  

    main.xml,其代码如下:

    [html] view plaincopy
    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    3.     android:layout_width="fill_parent"  
    4.     android:layout_height="fill_parent"  
    5.     android:orientation="vertical" >  
    6. <TableLayout    
    7.      android:layout_width="fill_parent"  
    8.     android:layout_height="wrap_content"  
    9.     >  
    10.     <TableRow   
    11.     android:gravity="center">  
    12.     <TextView   
    13.     android:layout_width="fill_parent"  
    14.     android:layout_height="wrap_content"  
    15.     android:textSize="20sp"  
    16.     android:text="手机号注册"/>  
    17.     </TableRow>  
    18.       
    19. </TableLayout>  
    20.  <TableLayout    
    21.      android:layout_width="fill_parent"  
    22.     android:layout_height="wrap_content"  
    23.     >  
    24.     <TableRow   
    25.     android:gravity="left">  
    26.     <TextView   
    27.     android:layout_width="fill_parent"  
    28.     android:layout_height="wrap_content"  
    29.     android:text="手机号:"/>  
    30.     <EditText   
    31.     android:layout_width="fill_parent"  
    32.     android:layout_height="wrap_content"  
    33.     android:hint="请输入手机号码..."  
    34.     android:id="@+id/phone"  
    35.         />  
    36.     </TableRow>  
    37.       
    38. </TableLayout>     
    39.     <TableLayout    
    40.      android:layout_width="fill_parent"  
    41.     android:layout_height="wrap_content"  
    42.     >  
    43.     <TableRow>  
    44.     <Button   
    45.     android:layout_width="fill_parent"  
    46.     android:layout_height="wrap_content"  
    47.     android:text="免费获取短信激活码"  
    48.     android:id="@+id/sendnumber"  
    49.         />  
    50.     </TableRow>  
    51.       
    52. </TableLayout>  
    53.     <TableLayout    
    54.      android:layout_width="fill_parent"  
    55.     android:layout_height="wrap_content"  
    56.     >  
    57.     <TableRow   
    58.     android:gravity="left">  
    59.     <TextView   
    60.     android:layout_width="fill_parent"  
    61.     android:layout_height="wrap_content"  
    62.     android:text="手短信激活码:"/>  
    63.     <EditText   
    64.     android:layout_width="fill_parent"  
    65.     android:layout_height="wrap_content"  
    66.     android:hint="输入激活码..."  
    67.     android:id="@+id/number"  
    68.         />  
    69.     <TextView   
    70.          android:layout_width="fill_parent"  
    71.          android:layout_height="wrap_content"  
    72.          android:id="@+id/counttime"  
    73.         />  
    74.     </TableRow>  
    75.       
    76. </TableLayout>     
    77. <TableLayout    
    78.      android:layout_width="fill_parent"  
    79.     android:layout_height="wrap_content"  
    80.     >  
    81.     <TableRow   
    82.     android:gravity="left">  
    83.     <TextView   
    84.     android:layout_width="fill_parent"  
    85.     android:layout_height="wrap_content"  
    86.     android:text="密码:"/>  
    87.     <EditText   
    88.     android:layout_width="fill_parent"  
    89.     android:layout_height="wrap_content"  
    90.     android:password="true"  
    91.     android:hint="请输入密码..."  
    92.     android:id="@+id/paw"  
    93.         />  
    94.     </TableRow>  
    95.       
    96. </TableLayout>    
    97. <TableLayout    
    98.      android:layout_width="fill_parent"  
    99.     android:layout_height="wrap_content"  
    100.     >  
    101.     <TableRow   
    102.     android:gravity="left">  
    103.     <CheckBox  
    104.     android:layout_width="fill_parent"  
    105.     android:layout_height="wrap_content"  
    106.     android:id="@+id/agree"   
    107.     android:checked="true"/>  
    108.     <TextView   
    109.     android:layout_width="fill_parent"  
    110.     android:layout_height="wrap_content"  
    111.     android:text="@string/links"/>  
    112.     </TableRow>  
    113.       
    114. </TableLayout>  
    115.    <TableLayout    
    116.      android:layout_width="fill_parent"  
    117.     android:layout_height="wrap_content"  
    118.     >  
    119.     <TableRow android:gravity="center">  
    120.     <Button   
    121.     android:layout_width="fill_parent"  
    122.     android:layout_height="wrap_content"  
    123.     android:textSize="30sp"  
    124.     android:text="注册"  
    125.     android:id="@+id/send"  
    126.     android:background="@color/skyblue"  
    127.         />  
    128.     </TableRow>  
    129.       
    130. </TableLayout>  
    131. </LinearLayout>  


    下面来看主Activity文件,其内容如下:下面来看Activity文件,其代码如下:

    [html] view plaincopy
    1. import java.util.logging.Logger;  
    2.   
    3. import java.util.regex.Matcher;  
    4. import java.util.regex.Pattern;  
    5.   
    6. import android.app.Activity;  
    7. import android.app.PendingIntent;  
    8. import android.content.Intent;  
    9. import android.os.Bundle;  
    10. import android.os.CountDownTimer;  
    11. import android.telephony.gsm.SmsManager;  
    12. import android.telephony.gsm.SmsMessage;  
    13. import android.view.View;  
    14. import android.view.View.OnClickListener;  
    15. import android.widget.Button;  
    16. import android.widget.CheckBox;  
    17. import android.widget.EditText;  
    18. import android.widget.TextView;  
    19. import android.widget.Toast;  
    20.   
    21. public class SendregActivity extends Activity {  
    22.     /** Called when the activity is first created. */  
    23.        
    24.     Button sendnumber,send;  
    25.     EditText phone,pwd,number;  
    26.     String temp="";  
    27.     String phonenum="";  
    28.     CheckBox agree;  
    29.     TimeCount timeco;  
    30.     TextView timecount;  
    31.     @Override  
    32.     public void onCreate(Bundle savedInstanceState) {  
    33.         super.onCreate(savedInstanceState);  
    34.         setContentView(R.layout.main);  
    35.         sendnumber=(Button) findViewById(R.id.sendnumber);  
    36.         send=(Button) findViewById(R.id.send);  
    37.         phone=(EditText) findViewById(R.id.phone);  
    38.         pwd=(EditText) findViewById(R.id.paw);  
    39.         number=(EditText) findViewById(R.id.number);//激活码  
    40.         agree=(CheckBox) findViewById(R.id.agree);  
    41.         timecount=(TextView) findViewById(R.id.counttime);  
    42.         timeco = new TimeCount(120000, 1000);//时间为120秒  
    43.         sendnumber.setOnClickListener(new OnClickListener() {  
    44.               
    45.             @Override  
    46.             public void onClick(View v) {  
    47.                 // TODO Auto-generated method stub  
    48.                 for(int i=0;i<5;i++){//产生一个五位数的激活码  
    49.                     int k=(int) (Math.random()*10);  
    50.                     temp+=k;  
    51.                 }  
    52.                   
    53.                 phonenum=phone.getText().toString().trim();  
    54.                 SmsManager smsmanger=SmsManager.getDefault();  
    55.                 if(isPhoneNumberValid(phonenum)){  
    56.                     PendingIntent mPI=PendingIntent.getBroadcast(SendregActivity.this, 0, new Intent(), 0);  
    57.                     smsmanger.sendTextMessage(phonenum, null, "你的激活码是:"+temp, mPI, null);  
    58.                     Toast.makeText(SendregActivity.this, "激活码发送成功!", Toast.LENGTH_LONG).show();  
    59.                      timeco.start();  
    60.                 }  
    61.                 else{  
    62.                     Toast.makeText(SendregActivity.this, "电话格式不正确,请检查!", Toast.LENGTH_LONG).show();  
    63.                 }  
    64.                   
    65.             }  
    66.         });  
    67.         send.setOnClickListener(new OnClickListener() {  
    68.               
    69.             @Override  
    70.             public void onClick(View v) {  
    71.                 // TODO Auto-generated method stub  
    72.                  phonenum=phone.getText().toString().trim();  
    73.                 if(!isPhoneNumberValid(phonenum)){  
    74.                     Toast.makeText(SendregActivity.this, "电话格式不正确,请检查!", Toast.LENGTH_LONG).show();  
    75.                 }  
    76.                 else if(phonenum.length()==0){  
    77.                     Toast.makeText(SendregActivity.this, "请输入电话号码!", Toast.LENGTH_LONG).show();  
    78.                 }  
    79.                 else if(number.getText().toString().trim().length()==0){  
    80.                     Toast.makeText(SendregActivity.this, "请输入激活码!", Toast.LENGTH_LONG).show();  
    81.                 }  
    82.                 else if(!number.getText().toString().equals(temp)){  
    83.                     Toast.makeText(SendregActivity.this, "激活码不正确!", Toast.LENGTH_LONG).show();  
    84.                 }  
    85.                 else if(pwd.getText().toString().trim().length()<6||pwd.getText().toString().trim().length()>12){  
    86.                     Toast.makeText(SendregActivity.this, "密码不能少于6为多余12位!!", Toast.LENGTH_LONG).show();  
    87.                 }  
    88.                 else if(!agree.isChecked()){  
    89.                     Toast.makeText(SendregActivity.this, "请先阅读百度协议!!", Toast.LENGTH_LONG).show();  
    90.                 }  
    91.                 else{  
    92.                     Toast.makeText(SendregActivity.this, "注册成功!", Toast.LENGTH_LONG).show();  
    93.                     timeco.cancel();  
    94.                 }  
    95.             }  
    96.         });  
    97.     }  
    98.     /*检查字符串是否为电话号码的方法,并回传true or false的判断值*/  
    99.     public static boolean isPhoneNumberValid(String mobiles){    
    100.          Matcher m = null;  
    101.         if(mobiles.trim().length()>0){  
    102.         Pattern p = Pattern.compile("^((13[0-9])|(15[0-3])|(15[7-9])|(18[0,5-9]))\\d{8}$");       
    103.         mp.matcher(mobiles);       
    104.         }  
    105.         else{  
    106.                
    107.             return false;  
    108.         }  
    109.         return m.matches();       
    110.     }   
    111.     /* 定义一个倒计时的内部类 */  
    112.     class TimeCount extends CountDownTimer {  
    113.     public TimeCount(long millisInFuture, long countDownInterval) {  
    114.     super(millisInFuture, countDownInterval);//参数依次为总时长,和计时的时间间隔  
    115.     }  
    116.     @Override  
    117.     public void onFinish() {//计时完毕时触发  
    118.    temp="";  
    119.    Toast.makeText(SendregActivity.this, "超时,需要重新发送激活码!", Toast.LENGTH_LONG).show();  
    120.     }  
    121.     @Override  
    122.     public void onTick(long millisUntilFinished){//计时过程显示  
    123.      
    124.     timecount.setText("倒计时:"+millisUntilFinished /1000+"秒");  
    125.     }  
    126.     }  
    127. }  

    程序要调用SmsManager来发送短信,因此还需要授予改程序发送短信的权限,也就是在AndroidManifest.xml文件中增加如下代码:

    [html] view plaincopy
    1. <uses-permission android:name="android.permission.SEND_SMS"/>  
    补充:需要用户支付短信费用。




    展开全文
  • django注册发送邮箱激活账号

    千次阅读 2019-05-19 01:10:08
    本篇博客写发送邮箱验证码,后续写发送手机验证码。 首先可以配置邮箱的一些必须的参数等 如,张三来注册 x 网站,邮箱是zhangsan@163.com,那么这个邮箱会收到激活链接,那么给他发送链接的邮箱是什么,需要我们 ...

    在用django开发项目时,会用到注册账号发送邮箱来激活账号或接收手机验证码。

    本篇博客写发送邮箱验证码,后续写发送手机验证码。

    首先可以配置邮箱的一些必须的参数等
    如,张三来注册 x 网站,邮箱是zhangsan@163.com,那么这个邮箱会收到激活链接,那么给他发送链接的邮箱是什么,需要我们 自己配置,在全局的settings.py中

    EMAIL_HOST = 'smtp.163.com'  # 163邮箱的 SMTP 地址
    
    EMAIL_PORT = 25     # SMTP端口
    
    EMAIL_HOST_USER = 'huamuxiong_2018@163.com'       # 我自己的邮箱
    
    EMAIL_HOST_PASSWORD = '****************'       # 我的邮箱授权码
    
    EMAIL_SUBJECT_PREFIX = '[huamuxiong]'     # 为邮件Subject-line前缀,默认是'[django]'
    
    EMAIL_USE_TLS = False   # 与SMTP服务器通信时,是否启动TLS链接(安全链接)。默认是false
    
    EMAIL_FROM = 'huamuxiong_2018@163.com'  # 与 EMAIL_HOST_USER 相同
    

    授权码获取方式:
    在这里插入图片描述
    在这里插入图片描述
    前期工作:
    写验证码的models

    # 邮箱--用来激活账号和找回密码
    class EmailPro(models.Model):
        code = models.CharField(max_length=20, verbose_name='验证码')
        email = models.EmailField(max_length=50, verbose_name='邮箱')
        send_type = models.CharField(max_length=10, choices=(('register', '邮箱注册'), ('forget', '忘记密码')), verbose_name='发送类型')
        send_time = models.DateTimeField(auto_now_add=True, verbose_name='发送时间')
    
        class Meta:
            db_table='emailpro'
            verbose_name='邮箱验证码'
            verbose_name_plural=verbose_name
    

    生成随机验证码的函数:
    randomlength:生成多少位的字符串,默认是 8 位

    from random import Random
    # 随机生成字符串
    def random_str(randomlength=8):
        str = ''
        chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
        length = len(chars)-1
        random = Random()
        for i in range(randomlength):
            str += chars[random.randint(0, length)]
        return str   # 将拼接的字符串返回
    

    写发送邮箱的函数:

    from django.core.mail import send_mail
    
    from index.models import EmailPro
    from rentingHouse.settings import EMAIL_FROM  # 项目名称为 rentingHouse
    
    # 接收两个参数,一个邮箱,另一个是发送类型,注册或忘记密码
    def send_register_email(email, send_type='register'):  # 类型为注册
        email_recode = EmailPro()
        code = random_str(16)  # 生成16位的随机字符串
        email_recode.code = code
        email_recode.email = email
        email_recode.send_type = send_type
        email_recode.save()
    
        email_title = ''
        email_body = ''
        if send_type == 'register':
            email_title = '注册激活链接'
            email_body = '请点击下方的链接激活你的账号:http://127.0.0.1:8000/active/{0}'.format(code)
        else:
            pass  # 忘记密码--暂时不写
        send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])  # 注释 ①
        if send_status:
            pass
    

    注释 ①:
    看一下必传的四个参数:
    subject: 主题,也就是 标题 title
    message:消息,也就是 内容 body
    from_email:发送的邮箱 配置中的 EMAIL_FROM
    recipient_list:收件人清单,要求是列表 ,[email1, email2,…],只有一个的话也是列表[email]

    send_mail会返回一个结果,可对结果做简单的处理,这里不写

    def send_mail(subject, message, from_email, recipient_list,
                  fail_silently=False, auth_user=None, auth_password=None,
                  connection=None, html_message=None):
    

    在注册时,让 isActice 设置为False,即不激活

    ...  # 验证邮箱是否存在,两次密码是否一致等,直接简写了
    email = request.POST.get('email', '')
    password = request.POST.get('password', '')
    password = make_password(password)  # 密码加密
    
    # 将注册信息添加到数据库的user表中
    obj = User(email=email, username=username, password=password, isActive=False)
    obj.save()
    send_register_email(email, 'register')  # 调用发送邮件的方法
    

    注册页面,使用leyton01@protonmail.com邮箱注册
    在这里插入图片描述
    登陆protonmail邮箱查看一下
    在这里插入图片描述
    显示的是一个主题 title 和 发送者邮箱
    点进去看一下
    在这里插入图片描述
    由于未搭建服务器, 所以暂时还是本地地址 127.0.0.1

    在登陆时根据isActive是否为True来判断账号是否被激活,上述说到False为没激活
    False —> 0

    if user.isActive == 0:
        return render(request, 'login.html', {'error_msg': '账号尚未激活'})
    

    在这里插入图片描述
    说明:这里我暂时用的用户名username,可以设置成邮箱,或这个两者都可以登陆的那种(借助Q),这里不说了

    那么在邮箱里点击链接后,需要做的就是让isActive=True

    class ActiveUserView(View):
        def get(self, request, active_code):
            all_codes = EmailPro.objects.filter(code=active_code)
            if all_codes:
                for recode in all_codes:
                    email = recode.email
                    user = User.objects.get(email=email)
                    user.isActive=True
                    user.save()
                return redirect('/login/')
            else:
                return render(request, 'code_fail.html')
    

    用到的url

    url('^active/(?P<active_code>.*)/$', ActiveUserView.as_view(), name='active_code'),  # 注册激活链接
    

    至此本篇文章结束

    展开全文
  • 手机验证:填写手机号码,点击发送验证码,接收后填写验证码比对,无误后注册成功。 邮箱验证:注册时填写邮箱账号,点击注册,网站邮箱会给该邮箱发送一封激活邮件,用户点击后激活该账号。 这里通过实例来介绍...

    手机验证:填写手机号码,点击发送验证码,接收后填写验证码比对,无误后注册成功。

    邮箱验证:注册时填写邮箱账号,点击注册,网站邮箱会给该邮箱发送一封激活邮件,用户点击后激活该账号。

     

    这里通过实例来介绍一下邮箱验证的实现过程,例子可以运行,暂时没有发现什么问题,不过也可能有不安全的地方,欢迎大家指正。

     

    实现思路

    注册时填写邮箱,点击注册时网站系统邮箱发送激活验证链接到此邮箱,用户来激活账户

    点击注册,系统邮箱会发送一封激活邮件到你填写的邮箱账号中


    在没有进行激活操作前,设定某个字段状态是0,表示此账号未激活,不可以使用或者某些功能受限


    激活操作之后,将activated字段更新为1,这样就完成了激活操作

    那么这里还有一个codeUrl字段,他的作用是存入一个唯一标识的随机码,这个随机码由用户名和UUID唯一标识的随机数组成,这样做的目的是防止用户使用不存在的邮箱又修改链接中的参数来激活账户,将链接中的随机码和数据库中的比对,来达到相对安全的激活。

     

    下面是具体的代码

    首先是注册的servlet,这里主要测试激活账号的功能,注册代码有点low,不安全,将就看一下

    package org.amuxia.emailtest.servlet;
     
    import java.io.IOException;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.UUID;
     
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
     
    import org.amuxia.emailtest.pojo.User;
    import org.amuxia.emailtest.utils.EmailUtils;
    import org.amuxia.emailtest.utils.MyJDBC;
     
    /**
     * @author amuxia
     * 2017年7月24日
     */
    @WebServlet("/RegistServlet")
    public class RegistServlet extends HttpServlet {  
        private static final long serialVersionUID = 1L;  
      
        protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
            String username = request.getParameter("username");  
            String password = request.getParameter("password");  
            String email = request.getParameter("email"); 
            String codeUrl = UUID.randomUUID().toString();
            User user = new User(); 
            user.setUsername(username);  
            user.setPassword(password);  
            user.setEmail(email);  
            user.setActivated(false);  //刚注册默认是没有激活状态
            String SQL = "insert into tb_user(username,password,email,activated,codeUrl) value (?,?,?,?,?) ";
            MyJDBC.insert(SQL, false, username,password,email,0,codeUrl);//注册信息插入数据库
            String querySQL = "select * from tb_user where email=?";
            ResultSet rs = MyJDBC.query(querySQL, email);
            try {
                if(rs.next()){
                    user.setId(rs.getInt(1));
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            // 注册成功后,发送帐户激活链接  
            request.getSession().setAttribute("user", user); 
            EmailUtils.sendAccountActivateEmail(user); 
            request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request,response);  
        }  
     
    }

    激活账号的Servlet,也就是更新操作
    package org.amuxia.emailtest.servlet;
     
    import java.io.IOException;
    import java.sql.ResultSet;
    import java.sql.SQLException;
     
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
     
    import org.amuxia.emailtest.pojo.User;
    import org.amuxia.emailtest.utils.GenerateLinkUtils;
    import org.amuxia.emailtest.utils.MyJDBC;
     
    /**
     * @author amuxia
     * 2017年7月24日
     */
    @WebServlet("/ActivateServlet")
    public class ActivateServlet extends HttpServlet{
        private static final long serialVersionUID = 1L;
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        String idValue = request.getParameter("id");
        System.out.println(idValue);
        int id = -1;
        try {
            id = Integer.parseInt(idValue);
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        String SQL = "select * from tb_user where id=?";
        ResultSet rs= MyJDBC.query(SQL, id);
        User user = new User();
        try {
            if(rs.next()){
                user.setId(rs.getInt(1));
                user.setUsername(rs.getString(2));
                user.setPassword(rs.getString(3));
                user.setEmail(rs.getString(4));
                user.setActivated(rs.getBoolean(5));
                user.setCodeUrl(rs.getString(6));
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //验证无误,状态更改为1,即激活
        if(GenerateLinkUtils.verifyCheckcode(user, request)){
            String updSQL = "update tb_user set activated =1 where id=?";
            MyJDBC.execute(updSQL, id);
            user.setActivated(true);
            request.getSession().setAttribute("user", user);
            request.getRequestDispatcher("/WEB-INF/jsp/pass.jsp").forward(request, response);
        }
        }
    }

    发送Email的工具类
    package org.amuxia.emailtest.utils;
     
    import java.util.Date;
    import java.util.Properties;
     
    import javax.mail.Authenticator;
    import javax.mail.Message.RecipientType;
    import javax.mail.PasswordAuthentication;
    import javax.mail.Session;
    import javax.mail.Transport;
    import javax.mail.internet.InternetAddress;
    import javax.mail.internet.MimeMessage;
     
    import org.amuxia.emailtest.pojo.User;
     
    /**
     * @author amuxia
     * 2017年7月24日
     */
    public class EmailUtils {
        
        private static final String FROM = "要发送邮件的邮箱,这个例子是163邮箱";
     
        public static void sendAccountActivateEmail(User user) {
            Session session = getSession();
            MimeMessage message = new MimeMessage(session);
            try {
                message.setSubject("这是一封激活账号的邮件,复制链接到地址栏来激活他");
                message.setSentDate(new Date());
                message.setFrom(new InternetAddress(FROM));
                message.setRecipient(RecipientType.TO, new InternetAddress(user.getEmail()));
                message.setContent("<a  target='_BLANK' href=''>"+GenerateLinkUtils.generateActivateLink(user)+"</a>","text/html;charset=utf-8");
                Transport.send(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
     
        
        public static Session getSession() {
            Properties props = new Properties();
            props.setProperty("mail.transport.protocol", "smtp");
            props.setProperty("mail.smtp.host", "smtp.163.com");
            props.setProperty("mail.smtp.port", "25");
            props.setProperty("mail.smtp.auth", "true");
            Session session = Session.getInstance(props, new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(FROM, "上面邮箱的密码");
                }
                
            });
            return session;
        }
    }
    这里需要注意一下,以上例子配置的是163邮箱,需要进行邮箱客户端的授权,授权之后,网易邮箱会发来一份客户端授权码作为替代邮箱密码,代码里填写的密码其实是授权码,配置好邮箱最好发一份邮件测试一下,有时程序出问题很可能是邮箱客户端根本发不了邮件
    加密账户激活链接生成的工具类

    package org.amuxia.emailtest.utils;
     
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
     
    import javax.servlet.ServletRequest;
     
    import org.amuxia.emailtest.pojo.User;
     
    /**
     * @author amuxia
     * 2017年7月24日
     */
    public class GenerateLinkUtils {
        
        private static final String CHECK_CODE = "checkCode";
        
        public static String generateActivateLink(User user) {
            return "http://localhost/EmailDemo/ActivateServlet?id=" 
                    + user.getId() + "&" + CHECK_CODE + "=" + generateCheckcode(user);
        }
        
        
        /**
         * 生成校验码,用户名+UUID唯一标识符,为安全把他们加密发送
         * @param user
         * @return
         */
        public static String generateCheckcode(User user) {
            String userName = user.getUsername();
            String randomCode = user.getCodeUrl();
            return md5(userName + ":" + randomCode);
        }
     
        
        /**
         * 接收回来的校验码和发送出去的是不是同一份
         * @param user
         * @param request
         * @return
         */
        public static boolean verifyCheckcode(User user,ServletRequest request) {
            String checkCode = request.getParameter(CHECK_CODE);
            System.out.println(generateCheckcode(user).equals(checkCode));
            return true;
        }
     
        private static String md5(String string) {
            MessageDigest md = null;
            try {
                md = MessageDigest.getInstance("md5");
                md.update(string.getBytes());
                byte[] md5Bytes = md.digest();
                return bytes2Hex(md5Bytes);
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
                System.out.println("md5这里出错了");
            }
            
            return null;
        }
        
        private static String bytes2Hex(byte[] byteArray)
        {
            StringBuffer strBuf = new StringBuffer();
            for (int i = 0; i < byteArray.length; i++)
            {
                if(byteArray[i] >= 0 && byteArray[i] < 16)
                {
                    strBuf.append("0");
                }
                strBuf.append(Integer.toHexString(byteArray[i] & 0xFF));
            }
            return strBuf.toString();
        }
     
    }

    还有一个操作数据库的封装类,MyJDBC,前面博客有写,代码挺长,就不贴了,这是链接:http://blog.csdn.net/weixin_36380516/article/details/72904214
    实体类User

    package org.amuxia.emailtest.pojo;
     
    public class User {
        private int id;
        private String username;
        private String password;
        private String email;
        private boolean activated;//账号状态
        private String codeUrl;//激活链接中的随机码
        
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
        public String getEmail() {
            return email;
        }
        public void setEmail(String email) {
            this.email = email;
        }
     
        public boolean isActivated() {
            return activated;
        }
        public void setActivated(boolean activated) {
            this.activated = activated;
        }
        public String getCodeUrl() {
            return codeUrl;
        }
        public void setCodeUrl(String codeUrl) {
            this.codeUrl = codeUrl;
        }
        public User() {
            super();
            
        }
        
    }

    注册的jsp
    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
     
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
    <head>
     
    <title>注册</title>
    </head>
     
    <body>
        <form action="/EmailDemo/RegistServlet" method="post">
            用户名:<input type="text" name="username"><br/>
            密码:<input type="password" name="password"><br/>
            邮箱:<input type="text" name="email"><br/>
            <input type="submit" value="注册">
        </form>
    </body>
    </html>

    展开全文
  • 模仿一些网站在注册的时候要填写手机号码,然后点击获取激活码,将会产生一个激活码,用短信的方式发到注册者的手机,然后用户需要查看短信,将激活码填写在注册页面,有时间限制。若超时则需要重新发送。  ...
  • 现在还在用Email的大部分是工作需要,私人的话顶多就是收收网站验证码激活邮件之类的。因此大多数人在手机上已经没有像PC时代般如此渴求一个好的邮件客户端。苹果用户们还好,iOS上不乏一些设计精美功能齐全的邮箱...
  • 每次注册app或者网站时候,都超麻烦,有的需要手机发送验证码,有的需要去邮箱激活,真的是挑战人的耐性!作为一个未来的产品大佬,你有没有思考过:为什么用户在注册时需要使用邮箱或手机号作为注册名? 本题考查的...
  • 激活账户需要充值30微分(一元一微分)微分用于预约宠物的(可以理解成公司收的手续费,毕竟只有公司赚钱了,我们才能赚钱)。 新用户有两种获取微分的方式:(1)自已后台充值,一次最少充值50微分;(2)找上级转...
  • 个人博客网站编写(03)   前言:上一篇讲的是关于SSM框架的整合,本篇文章将会展示如何设计博客的业务表及通过Mybatis的代码生成工具进行代码实体类的生成。 我们接下来我们通过要完成的功能来分析可能会存在的...
  • 而注册激活账号一般有两种形式,一种是手机短信验证码激活,另一种是邮箱激活。今天主要讲述使用邮件 如需Springboot发送短信,还请查看我的另一博文Springboot整合阿里云短信SDK发送短信验证码笔记 二、整合开发 ...
  • 仿给你花借贷系统借款分期含支付,已经二次开发 把...安装完成后进入后台网站设置,将网站地址修改为你的网站地址 地址末尾不带"/" 源码亲测好用 一经售出不是源码问题不退款 安装费另算 后台默认密码 admin admin
  • WEB开发中经常会用到倒计时来限制用户对表单的操作,比如希望用户在一定时间内看完相关协议信息才允许用户继续下一步操作,又比如在收取手机验证码时允许用户在一定时间过后(未收到验证码的情况下)再次获取验证码...
  • 2020-01-03

    2020-01-03 10:34:26
    当进入一个网站时首先进行注册,注册时会提示输入手机号,利用阿里大鱼接口发送一条短信验证码到当前号码并将短信验证码保存到redis;注册时会提示输入邮箱账号,当点击注册时会给当前邮箱发送一条激活码给用户激活 ...
  • 【JAVA】代码也错了

    2019-05-03 19:56:46
    手机验证:填写手机号码,点击发送验证码,接收后填写验证码比对,无误后注册成功。 邮箱验证:注册时填写邮箱账号,点击注册,网站邮箱会给该邮箱发送一封激活邮件,用户点击后激活该账号。 这里通过实例来介绍...
  • WEB开发中经常会用到倒计时来限制用户对表单的操作,比如希望用户在一定时间内看完相关协议信息才允许用户继续下一步操作,又比如在收取手机验证码时允许用户在一定时间过后(未收到验证码的情况下)再次获取验证码...
  •  进入今日头条网站,点击页面右上角的“头条号”。... 输入手机号码,点击发送验证码,然后输入手机收到的短信验证码,点击“确定”。 然后显示绑定手机成功,请前往邮箱激活帐号。 然后要求...
  • 在本些views中,可能需要执行一段耗时的程序,那么用户就会等待很长时间,造成不好的用户体验,比如发送邮件、手机验证码等。 使用celery后,情况就不一样了。解决:将耗时的程序放到celery中执行。 我们在做网站...
  • Zoom视频会议软件使用

    千次阅读 2020-02-19 10:48:07
    手机或者电脑浏览器输入网址注册 访问zoom.com.cn,点击网站首页左下角的“立即免费注册”按钮 2.使用邮箱注册账户 输入邮箱和验证码,点击“注册”按钮 注:由于个人邮箱接收Zoom激活账户邮件有延迟,建议填写...
  • 让我们花三分钟创建一个小程序! ...访问微信公众平台网站:https://mp.weixin.qq.com 鼠标放到小程序上 ...2. 激活邮箱 这个时候你会收到一封邮件...选个人,下面的信息无脑填写,然后获取手机验证码,扫码确认管理员
  • DreamSpark是什么东西,我相信很多的中国学生都应该知道吧,至少我们可以从那里得到很多免费的正版软件,而验证呢获取有时候难住我们了,虽然现在一个edu的邮箱很容易,那么有没有使用过验证码激活的呢?...
  • 为了重用校验码的逻辑,网站系分主导,将校验码的生成、验证规则放在会员核心中(包含错误三次以上删除校验码,一分钟只能发送一次等规则),具体影响验证找回密码申请、手机绑定、手机解绑、激活增加登录号、注册时...
  • 项目案例:基于Celery、Redis... 和经常我们在注册信息的时候,发送激活邮箱,手机发送验证码 按时发布的定时任务,如定期对服务器的检查,对当天网站的监测分析。 补充 (1) 同步和异步的概念: 同步:你去饭店吃...
  • JustMedia主题是一款针对有图片或者视频发布需求的网站量身定制开发的...新支持腾讯云短信接口发送验证码; 新支持用户分组; 新支持用户注册邮件激活/人工审核; 新支持文章图片lightbox灯箱功能; 新支持微信内置
  • 可能通过热键直接激活功能进行操作,是网页编辑的必不可少实用工具。同时还可以将一些轻常性的文本保存下来,下次可以通过热键功能可以直接将内容投放到指定光标的输入区域,是填表或经常重复制粘贴操作的一个好帮手...
  • 5、如果不想手机短信激活帐户的,可以联系卖家在线修改源码(提供FTP地址、帐号和密码) 6、邮箱设置,开启smtp服务。 7、部分页面文字,可以在后台-工具-替换(注意:请确认替换的文字在其位置的唯一性) 8...
  • 实例174 利用Servlet生成动态验证码 实例175 避免客户端访问的并发问题 实例176 在Servlet中使用JDBC访问数据库 实例177 利用Servlet访问数据库连接池 实例178 Servlet实现的个人所得税计算器 实例179 利用...
  • 实例174 利用Servlet生成动态验证码 实例175 避免客户端访问的并发问题 实例176 在Servlet中使用JDBC访问数据库 实例177 利用Servlet访问数据库连接池 实例178 Servlet实现的个人所得税计算器 实例179 利用...
  • 数据运营思维导图

    2018-04-26 14:24:22
    如:多次获取手机验证码,次数剧增 这里需要考虑有一个监控指标 新功能数据分析 通过留存曲线检验新功能的效果 通过留存看新功能用户的接受程度 通过用户反馈或调研,了解新功能接受度 数据指标 标记: 红色 ...
  • 2019数据运营思维导图

    2019-03-29 21:34:09
    数据库、运营后台等 工作内容 数据监控 检测异常指标,发现用户对您产品的”怒点“ 如:多次获取手机验证码,次数剧增 这里需要考虑有一个监控指标 新功能数据分析 通过留存曲线检验新功能的效果 通过留存看新功能...

空空如也

空空如也

1 2
收藏数 33
精华内容 13
关键字:

网站手机验证码激活