溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

手把手教你做JavaWeb項(xiàng)目:登錄模塊

發(fā)布時(shí)間:2020-09-27 20:03:45 來(lái)源:網(wǎng)絡(luò) 閱讀:378 作者:這個(gè)殺手有點(diǎn)冷 欄目:編程語(yǔ)言

現(xiàn)如今,無(wú)論是客戶(hù)端還是移動(dòng)端,無(wú)論是電動(dòng)登陸還是社交平臺(tái)登陸,無(wú)處不在的“登陸”。那么你知道怎么制作嗎?今天就為你娓娓道來(lái):

用戶(hù)登錄
在各大信息管理系統(tǒng)中,登錄功能是必不可少的,他的作用就是驗(yàn)證用戶(hù)的身份,判斷用戶(hù)是否是本站的會(huì)員,只有會(huì)員才能訪(fǎng)問(wèn)當(dāng)前系統(tǒng)
登錄的實(shí)現(xiàn)步驟:
1.用戶(hù)填寫(xiě)賬號(hào)和密碼,提交到后臺(tái)
2.后臺(tái)獲取到賬號(hào)和密碼后,將其發(fā)送到數(shù)據(jù)庫(kù)中進(jìn)行查詢(xún)
3.查詢(xún)結(jié)果如果為null,說(shuō)明用戶(hù)填寫(xiě)的賬號(hào)或者密碼有誤,應(yīng)該回到登錄頁(yè)面并提示用戶(hù)重新輸入
4.查詢(xún)結(jié)果如果不為null,說(shuō)明用戶(hù)填寫(xiě)的賬號(hào)和密碼正確,將對(duì)應(yīng)的賬戶(hù)信息共享到session中(在后面的請(qǐng)求,我們還需要繼續(xù)使用當(dāng)前登錄的用戶(hù)信息),然后跳轉(zhuǎn)到網(wǎng)站的主頁(yè)面
按照上面的步驟,我們使用下面的代碼完成了相應(yīng)功能
1.登錄頁(yè)面
<form class="form-horizontal" action="/login" method="post">
<div class="form-group">
<label for="inputEmail3" class="col-sm-3 control-label">用戶(hù)名</label>
<div class="col-sm-9">
<input type="text" name="name" class="form-control" id="inputEmail3">
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-3 control-label">密???碼</label>
<div class="col-sm-9">
<input type="password" name="password" class="form-control" id="inputPassword3">
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-3 control-label"></label>
<div class="col-sm-9">
<button type="submit" class="btn btn-default">登錄</button></div>
</div>
頁(yè)面中存在很多布局相關(guān)的代碼,大家可以直接略過(guò),重點(diǎn)看表單元素相關(guān)的標(biāo)簽即可
LoginServlet
@WebServlet("/login")
br/></div>
</div>
頁(yè)面中存在很多布局相關(guān)的代碼,大家可以直接略過(guò),重點(diǎn)看表單元素相關(guān)的標(biāo)簽即可
LoginServlet
@WebServlet("/login")
private IEmployeeService service = new EmployeeServiceImpl();

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String name = req.getParameter("name");
    String password = req.getParameter("password");
    Employee currentUser = service.login(name, password);
    if(currentUser==null){
        //登錄失敗
        req.setAttribute("errorMsg","親,賬戶(hù)或者密碼錯(cuò)誤");
        req.getRequestDispatcher("/login.jsp").forward(req,resp);
        return;
    }else{
        //登錄成功
        req.getSession().setAttribute("USER_IN_SESSION",currentUser);
        resp.sendRedirect("/employee");
        return;
    }

SQL:
SELECT * FROM employee WHERE name = ? AND password = ?
登錄失敗效果

手把手教你做JavaWeb項(xiàng)目:登錄模塊

登錄成功效果

手把手教你做JavaWeb項(xiàng)目:登錄模塊用戶(hù)注銷(xiāo)
用戶(hù)注銷(xiāo)功能的主要作用是保護(hù)用戶(hù)的賬戶(hù)安全,在用戶(hù)點(diǎn)擊安全退出的時(shí)候,我們需要將本次會(huì)話(huà)相關(guān)的session信息刪除
刪除的方式有下面兩種:
1.刪除當(dāng)前登錄的用戶(hù)信息
存在問(wèn)題:本次會(huì)話(huà)的其他信息還是保存在內(nèi)存中,沒(méi)有及時(shí)清理
@WebServlet("/logout")
br/>用戶(hù)注銷(xiāo)
用戶(hù)注銷(xiāo)功能的主要作用是保護(hù)用戶(hù)的賬戶(hù)安全,在用戶(hù)點(diǎn)擊安全退出的時(shí)候,我們需要將本次會(huì)話(huà)相關(guān)的session信息刪除
刪除的方式有下面兩種:
1.刪除當(dāng)前登錄的用戶(hù)信息
存在問(wèn)題:本次會(huì)話(huà)的其他信息還是保存在內(nèi)存中,沒(méi)有及時(shí)清理
@WebServlet("/logout")
private IEmployeeService service = new EmployeeServiceImpl();
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.getSession().removeAttribute("USER_IN_SESSION");
resp.sendRedirect("/login.jsp");
}
}
2.銷(xiāo)毀整個(gè)session(推薦)
@WebServlet("/logout")
br/>req.getSession().removeAttribute("USER_IN_SESSION");
resp.sendRedirect("/login.jsp");
}
}
2.銷(xiāo)毀整個(gè)session(推薦)
@WebServlet("/logout")
private IEmployeeService service = new EmployeeServiceImpl();
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getSession().invalidate();
resp.sendRedirect("/login.jsp");
}
}
驗(yàn)證碼
驗(yàn)證碼是每個(gè)系統(tǒng)必不可少的功能,主要是用來(lái)防止系統(tǒng)被惡意***,如果沒(méi)有這個(gè)功能,那么我們的系統(tǒng)就如同沒(méi)有上鎖的家門(mén)一樣,小偷隨時(shí)能進(jìn)來(lái)干壞事
所以我們來(lái)看看,在登錄的時(shí)候如何使用驗(yàn)證碼,其他模塊如果要使用,原理一樣

手把手教你做JavaWeb項(xiàng)目:登錄模塊

1.首先,需要在登錄頁(yè)面顯示出驗(yàn)證碼的圖片,用戶(hù)可以根據(jù)圖片中的文字進(jìn)行填寫(xiě)
2.同時(shí),在生成驗(yàn)證碼的時(shí)候,我們需要將正確的驗(yàn)證碼保存到session中,供后面校驗(yàn)使用
3.用戶(hù)填寫(xiě)好驗(yàn)證碼后,提交表單,后臺(tái)校驗(yàn)
注:生成驗(yàn)證碼的代碼不是我們這里的重點(diǎn),以后如果需要,在網(wǎng)上一搜一籮筐,所以我就不貼出來(lái)了
校驗(yàn)代碼
//校驗(yàn)驗(yàn)證碼是否正確
String randomcode_in_session = (String) req.getSession().getAttribute("RANDOMCODE_IN_SESSION");
String randomCode = req.getParameter("randomCode");
if (!StringUtils.isNullOrEmpty(randomCode) && !StringUtils.isNullOrEmpty(randomcode_in_session)) {
if (!randomCode.equals(randomcode_in_session)) {
Cookie nameCookie = new Cookie("name", name);
Cookie passwordCookie = new Cookie("password", password);
resp.addCookie(nameCookie);
resp.addCookie(passwordCookie);
handleError(req, resp, "親,驗(yàn)證碼錯(cuò)誤");
return;
}
} else {
handleError(req, resp, "驗(yàn)證碼不能為空或者驗(yàn)證碼已失效");
return;
}

private void handleError(HttpServletRequest req, HttpServletResponse resp, String errorMsg)
throws ServletException, IOException
req.getSession().setAttribute("errorMsg", errorMsg);
resp.sendRedirect("/login.jsp");
}
當(dāng)用戶(hù)沒(méi)填寫(xiě)驗(yàn)證碼或者session中的驗(yàn)證碼失效,都應(yīng)該給出錯(cuò)誤提示
如果用戶(hù)填寫(xiě)的和session中保存的驗(yàn)證碼不匹配,給出錯(cuò)誤提示
如此,當(dāng)驗(yàn)證碼不正確的時(shí)候,我們就不會(huì)繼續(xù)做登錄校驗(yàn),必須等用戶(hù)填寫(xiě)出正確的驗(yàn)證碼才可以,而這一點(diǎn),機(jī)器是無(wú)法做到的
記住賬號(hào)
該功能的目的主要是想在用戶(hù)一次登錄之后,下次可以不再重新填寫(xiě)賬號(hào),增加用戶(hù)體驗(yàn)
想要實(shí)現(xiàn)該功能,我們需要在后臺(tái)將用戶(hù)的賬號(hào)信息進(jìn)行共享
但是,我們應(yīng)該使用什么來(lái)完成共享呢?
來(lái),想想我們的需求,我今天早上十點(diǎn)第一次登陸系統(tǒng),使用完之后,關(guān)閉瀏覽器,下午還需要登陸幾次,明天后天...
那么我想在這種需求下都可以不再填寫(xiě)賬號(hào)
在這樣的需求下,我相信大家能夠想到一個(gè)答案---cookie
Cookie是將數(shù)據(jù)保存在瀏覽器中,而且,我們可以設(shè)置保存的時(shí)間,可以在關(guān)閉瀏覽器之后仍然能夠繼續(xù)使用
所以,Cookie就是我們?cè)谶@個(gè)需求中的最佳解決方案
在登錄的業(yè)務(wù)邏輯添加如下代碼,將賬號(hào)相關(guān)信息保存到使用Cookie進(jìn)行保存
//記住我
String rememberMe = req.getParameter("rememberMe");
if (!StringUtils.isNullOrEmpty(rememberMe)) {
//將用戶(hù)信息保存到Cookie中
Cookie nameCookie = new Cookie("name", name);
nameCookie.setMaxAge(60 60 24);

        Cookie rememberMeCookie = new Cookie("rememberMe", rememberMe);
        rememberMeCookie.setMaxAge(60 * 60 * 24);
        resp.addCookie(nameCookie);
        resp.addCookie(rememberMeCookie);
    } else {
        //將用戶(hù)信息從Cookie中移除
        Cookie[] cookies = req.getCookies();
        for (Cookie cookie : cookies) {
            if ("name".equals(cookie.getName())  || "rememberMe".equals(cookie.getName())) {
                cookie.setMaxAge(0);
                resp.addCookie(cookie);
            }
        }
    }

然后,在登錄頁(yè)面獲取到Cookie中的數(shù)據(jù)即可
<div class="form-group">
<label for="inputEmail3" class="col-sm-3 control-label">用戶(hù)名</label>
<div class="col-sm-9">
<input type="text" name="name" class="form-control" id="inputEmail3"
value="${cookie.name.value}">
</div>
</div>

<label>
<input type="checkbox" name="rememberMe"
${empty cookie.rememberMe.value?"":"checked='checked'"}> Remember me
</label>
當(dāng)選擇了記住我后,登錄錯(cuò)誤回到登錄頁(yè)面,此時(shí)能夠自動(dòng)獲取到上次的賬號(hào)信息

手把手教你做JavaWeb項(xiàng)目:登錄模塊
登錄檢查
在用戶(hù)沒(méi)有登錄的情況下,不允許訪(fǎng)問(wèn)系統(tǒng)中除登錄以外的其他模塊,如果訪(fǎng)問(wèn),應(yīng)該直接回到登錄頁(yè)面
在javaweb中,這個(gè)問(wèn)題的最佳解決方案就是使用過(guò)濾器(Filter)
過(guò)濾器:能夠在訪(fǎng)問(wèn)到達(dá)目標(biāo)資源之前對(duì)請(qǐng)求做預(yù)處理,在響應(yīng)離開(kāi)之前對(duì)響應(yīng)做預(yù)處理
在我們這個(gè)需求中,是需要對(duì)請(qǐng)求做預(yù)處理的,檢查用戶(hù)在請(qǐng)求當(dāng)前資源之前,是否已經(jīng)登錄
實(shí)現(xiàn)步驟:
1.定義過(guò)濾器:CheckLoginFilter
public class CheckLoginFilter implements Filter {
private List<String> needCheckURIs;

public void init(FilterConfig filterConfig) throws ServletException {
    //獲取到需要校驗(yàn)的資源名稱(chēng)(如果需要校驗(yàn)的資源較多,可以配置不需要校驗(yàn)的資源)
    String needCheckURI = filterConfig.getInitParameter("needCheckURI");
    String[] split = needCheckURI.split(",");
    //將所有的資源名存放到集合中,待后面進(jìn)行校驗(yàn)
    needCheckURIs = Arrays.asList(split);
}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) 
            throws IOException, ServletException {

    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse resp = (HttpServletResponse) response;
    //獲取當(dāng)前請(qǐng)求的資源名
    String requestURI = req.getRequestURI();
    //如果當(dāng)前請(qǐng)求的資源是不需要校驗(yàn)的,直接放行
    if(!needCheckURIs.contains(requestURI)){
        filterChain.doFilter(req, resp);
        return;
    }
    //如果需要校驗(yàn),判斷用戶(hù)是否登錄,是,則放行,反之回到登錄頁(yè)面
    Object currentUser = req.getSession().getAttribute("USER_IN_SESSION");
    if (currentUser == null) {
        resp.sendRedirect("/login.jsp");
        return;
    }
    filterChain.doFilter(req, resp);
}

public void destroy() {

}

}
2.將過(guò)濾器交給Tomcat服務(wù)器管理
<!--登錄檢查過(guò)濾器-->
<filter>
<filter-name>CheckLoginFilter</filter-name>
<filter-class>cn.wolfcode.javaweb.web.filter.CheckLoginFilter</filter-class>
<init-param>
<param-name>needCheckURI</param-name>
<param-value>/employee,/department</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CheckLoginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
有了該過(guò)濾器,用戶(hù)就不能再?zèng)]有登錄的時(shí)候,直接訪(fǎng)問(wèn)相關(guān)資源了,做到了一個(gè)基本的安全控制
生成系統(tǒng)賬戶(hù)
當(dāng)系統(tǒng)啟動(dòng)后,我們需要在用戶(hù)表中存在一個(gè)最起碼的管理員賬戶(hù),這樣,用戶(hù)才能登錄進(jìn)來(lái)來(lái)管理整個(gè)系統(tǒng)
那么,如何實(shí)現(xiàn)在啟動(dòng)服務(wù)器的時(shí)候,完成這個(gè)需求呢?
其實(shí)解決方案很多,大家也都應(yīng)該能想到
1.Servlet
Servlet默認(rèn)情況下是在第一次訪(fǎng)問(wèn)的時(shí)候執(zhí)行初始化操作
但是也可以調(diào)整到啟動(dòng)服務(wù)器的時(shí)候,<load-on-startup>0</load-on-startup>
初始化Servlet的時(shí)候,會(huì)執(zhí)行當(dāng)前Servlet的init方法
所以,我們完全在該方法中來(lái)完成這個(gè)需求
2.Filter
過(guò)濾器的初始化就是在啟動(dòng)服務(wù)器的時(shí)候
和Servlet一樣,初始化的時(shí)候會(huì)執(zhí)行Filter的init方法
所以,也可以在Filter的init方法中完成該需求
3.Listener
前面學(xué)習(xí)過(guò)WEB中的監(jiān)聽(tīng)器,知道他能夠?qū)ψ饔糜?創(chuàng)建/銷(xiāo)毀)和作用域中的屬性(添加/刪除/修改)進(jìn)行監(jiān)聽(tīng)
我們的需求是,在啟動(dòng)服務(wù)器的時(shí)候創(chuàng)建默認(rèn)賬戶(hù)
而在啟動(dòng)服務(wù)器的時(shí)候,application作用域?qū)ο髸?huì)在這個(gè)時(shí)候創(chuàng)建
綜上,我們可以創(chuàng)建一個(gè)application作用對(duì)象監(jiān)聽(tīng)器,在創(chuàng)建該對(duì)象的時(shí)候,完成默認(rèn)賬戶(hù)的創(chuàng)建
上面三種方式都能完成我們的需求,但最終從責(zé)任分離原則方面考慮,我們應(yīng)該選擇使用監(jiān)聽(tīng)器,實(shí)現(xiàn)如下
創(chuàng)建監(jiān)聽(tīng)器
public class SystemManagerCreaterListener implements ServletContextListener {
private IEmployeeService service = new EmployeeServiceImpl();
public void contextInitialized(ServletContextEvent servletContextEvent) {
//查詢(xún)系統(tǒng)默認(rèn)賬戶(hù)是否存在,如果不存在,創(chuàng)建一個(gè)默認(rèn)賬戶(hù)
Employee manager = service.selectSystemManager();
if(manager==null){
manager = new Employee();
manager.setName("admin");
manager.setPassword("1");
manager.setAdmin(true);
service.save(manager);
}
}

public void contextDestroyed(ServletContextEvent servletContextEvent) {

}

}
注冊(cè)監(jiān)聽(tīng)器
<listener>
<listener-class>cn.wolfcode.javaweb.web.listener.SystemManagerCreaterListener</listener-class>
</listener>
如此,在啟動(dòng)服務(wù)器的時(shí)候,先會(huì)到員工表中查詢(xún),是否存在默認(rèn)的管理員賬戶(hù)。
點(diǎn)擊查看JavaWeb系列的其它文章
手把手教你做JavaWeb項(xiàng)目:項(xiàng)目需求分析
手把手教你做JavaWeb項(xiàng)目:前臺(tái)界面
手把手教你做JavaWeb項(xiàng)目:多條件過(guò)濾
前往叩丁狼官網(wǎng)獲取更多技術(shù)視頻
看完了嗎?看完了就趕快行動(dòng)起來(lái),打開(kāi)你的編輯器,開(kāi)始編譯登陸界面實(shí)現(xiàn)登陸注冊(cè)吧!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI