日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java发送邮件链接实现登录注册

發(fā)布時(shí)間:2023/12/8 java 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java发送邮件链接实现登录注册 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

使用spring boot+OhMyEmail+Java-jwt實(shí)現(xiàn)整個(gè)過程
選用java-jwt的原因是因?yàn)轫?xiàng)目需要和python后端算法配合,使用token進(jìn)行通信,而python中的pyjwt庫對于簽名的處理與jjwt簽名的處理方式不一致,所以采用java-jwt實(shí)現(xiàn)Java端的jwt生成

通過圖片可以得知jjwt對于簽名轉(zhuǎn)成字節(jié)碼然后使用base64加密,這與官網(wǎng)jwt.io中對于前面的處理不一致。而java-jwt的簽名處理與jwt.io上的處理方式一致,從而使用pyjwt也可以通過相同密鑰進(jìn)行解密。

對于郵件,采用的是OhMyEmail庫,這個(gè)庫是國人封裝javax-Email的,對于發(fā)送常用的郵件格式做了很好的封裝。

  • 簡潔的郵件發(fā)送API
  • 支持自定義發(fā)件人昵稱
  • 支持?jǐn)U展郵件Message
  • 支持抄送/HTML/附件
  • 支持異步發(fā)送
  • 支持郵件模板
    我主要使用他的支持郵件模板這個(gè)特點(diǎn)
    對于整個(gè)過程的設(shè)計(jì),參考了一下網(wǎng)上的方案,由于我采用的郵件注冊,通過郵件中的鏈接進(jìn)行登錄。那么對于流程邏輯就涉及到了用戶選擇點(diǎn)擊或者不點(diǎn)擊鏈接登錄,或者用戶直接使用注冊時(shí)的賬號密碼嘗試登錄(即不點(diǎn)擊鏈接直接登陸,便失去了使用郵箱驗(yàn)證的意義)。所以對于不點(diǎn)擊我們可以采取在用戶表增加字段來判斷用戶是否已經(jīng)通過點(diǎn)擊鏈接登錄激活賬號。對于用戶點(diǎn)擊鏈接需要設(shè)置時(shí)效,這個(gè)可以token中的issedad以及expiredat字段屬性來進(jìn)行設(shè)計(jì),我設(shè)計(jì)的時(shí)效為一天。所以當(dāng)用戶超過時(shí)效進(jìn)行登錄是無效的,那么他再次嘗試注冊時(shí),就可以通過檢查新增字段中的屬性來判斷是否已經(jīng)注冊過但是尚未激活。簡而言之,失去時(shí)效即不可能登錄,登錄使用賬號密碼需要檢查是否激活,未激活就重新進(jìn)行注冊。未失去時(shí)效進(jìn)行點(diǎn)擊鏈接,則對新增字段屬性進(jìn)行重置激活。

記錄出現(xiàn)的問題:
問題1:前端設(shè)置"ContentType/json;charst=utf-8"
由于后端我們使用的RequestBody,前端需要傳輸json字符串,所以需要設(shè)置頭。同時(shí)處理前端數(shù)據(jù),使用JSON.Stringfy()將對象轉(zhuǎn)化為Json字符串。避免出現(xiàn)類型不匹配以及后端報(bào)錯(cuò)contenttype無法處理
問題2:發(fā)送郵件時(shí)使用 Pebble庫渲染html文件
這個(gè)渲染html文件,我在python做后端的時(shí)候用到過,比如flask以及fastapi都是通過template來進(jìn)行前端樣式渲染。但是在java中還是第一次使用。渲染時(shí),注意需要生成的html文件不要增加html的頭那些格式,只要html的body部分,不然會被處理為垃圾郵件自動攔截
其次就是對于html文件放置在src/java/resource下但是未被查找到,可能設(shè)置了文件過濾,在pom文件中對.html后綴文件進(jìn)行include即可被編譯到target中去

public class EmailUtil {//你的郵箱號public static final String username="xxxx@qq.com";//開啟smtp授予的授權(quán)碼public static final String password="xxxxxxxx";public static void initOhMyEmail(){OhMyEmail.config(OhMyEmail.SMTP_QQ(false),username,password);} } //使用郵箱注冊@PostMapping("registerByEmail")public R loginByEmail(@RequestBody User user) throws SendMailException {//進(jìn)行狀態(tài)設(shè)置 數(shù)據(jù)庫其實(shí)默認(rèn)設(shè)置為0 放在這里也只是為了提醒user.setState(0);String id=userService.register(user);String token=JwtAuth.getJavaToken(id, user.getEmail(),user.getPhoneNumber());//前端首頁地址 以parameter形式返回token 然后進(jìn)行登錄String loginUrl=constValue.INDEXURL+"?token="+token;//初始化Emailsender配置EmailUtil.initOhMyEmail();PebbleEngine engine = new PebbleEngine.Builder().build();//配置register模板文件PebbleTemplate compiledTemplate = engine.getTemplate("register.html");Map<String, Object> context = new HashMap<String, Object>();//配置模板文件中屬性context.put("username", user.getEmail());context.put("loginUrl",loginUrl);context.put("adminEmail", constValue.ADMINEMAIL);try {Writer writer = new StringWriter();compiledTemplate.evaluate(writer, context);String output = writer.toString();OhMyEmail.subject("這是一封來自某不知名禿頭大哥登錄驗(yàn)證的郵件").from("其實(shí)頭發(fā)很多哈哈哈").to(user.getEmail()).html(output).send();} catch (IOException e) {throw new DefinationException(20001,"發(fā)送郵件失敗");}return R.ok();} //register.html <div><p>親愛的<b>{{ username }}</b>, 歡迎加入 IIM !</p><p>當(dāng)您收到這封信的時(shí)候,您已經(jīng)可以正常登錄了。</p><p>請點(diǎn)擊鏈接登錄首頁: <a href="{{ loginUrl }}"> {{ loginUrl }}</a></p><p>如果您的 email 程序不支持鏈接點(diǎn)擊,請將上面的地址拷貝至您的瀏覽器(如IE)的地址欄進(jìn)入。</p><p>如果您還想申請管理員權(quán)限,可以聯(lián)系管理員 {{ adminEmail }}</p><p>我們對您產(chǎn)生的不便,深表歉意。</p><p>希望您在 IIM時(shí)序數(shù)據(jù)異常檢測 系統(tǒng)度過快樂的時(shí)光!</p><p></p><p>-----------------------</p><p></p><p>(這是一封自動產(chǎn)生的email,請勿回復(fù)。)</p> </div> //jwt工具類//常量public static final long EXPIRE = 1000 * 60 * 60 * 24; //token過期時(shí)間為一天public static final String APP_SECRET = "xclxzlxzlxzlxzlxzlxz"; //秘鑰//TODO 設(shè)置過期時(shí)間public static String getJavaToken(String id,String email,String phoneNumber){String token="";Map<String, Object> headerClaims = new HashMap<>();headerClaims.put("alg","HS256");headerClaims.put("typ","JWT");try{token= JWT.create().withHeader(headerClaims).withIssuedAt(new Date()).withExpiresAt(new Date(System.currentTimeMillis()+EXPIRE)).withClaim("id",id).withClaim("phoneNumber",phoneNumber).withClaim("email",email).sign(Algorithm.HMAC256(APP_SECRET));}catch(JWTCreationException | UnsupportedEncodingException e){System.out.println("創(chuàng)建java-jwt失敗");}return token;}//在verify時(shí)如果在header中增加了expiredat issuedAt等屬性 會自動驗(yàn)證時(shí)間,如果失效會報(bào)錯(cuò),捕捉錯(cuò)誤即可 public static String getMemberIdByJwtToken(HttpServletRequest request){String jwtToken = request.getHeader("token");if(StringUtils.isEmpty(jwtToken)) return "";JWTVerifier verifier=null;try{verifier= JWT.require(Algorithm.HMAC256(APP_SECRET)).build();} catch (UnsupportedEncodingException e) {e.printStackTrace();}DecodedJWT jwt=null;try{jwt=verifier.verify(jwtToken);}catch (SignatureVerificationException e){throw new DefinationException(20001,"token失效,重新登錄");}return jwt.getClaim("id").asString();}

貼出java-jwt 的builder下的方法,主要看看with開頭的方法即可
對于acceptleeway 我個(gè)人覺得沒什么必要了解,但是可以看看

總結(jié)

以上是生活随笔為你收集整理的Java发送邮件链接实现登录注册的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。