溫馨提示×

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

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

servlet如果實(shí)現(xiàn)簡(jiǎn)單的權(quán)限管理和敏感詞過(guò)濾功能

發(fā)布時(shí)間:2021-05-28 09:39:40 來(lái)源:億速云 閱讀:226 作者:小新 欄目:開發(fā)技術(shù)

這篇文章主要介紹了servlet如果實(shí)現(xiàn)簡(jiǎn)單的權(quán)限管理和敏感詞過(guò)濾功能,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

一、如何實(shí)現(xiàn)權(quán)限管理

1.思路

當(dāng)用戶訪問(wèn)某個(gè)資源時(shí),我們必須對(duì)其權(quán)限控制,所以得用到servlet中過(guò)濾器來(lái)對(duì)請(qǐng)求做一次預(yù)處理,判斷該用戶是否有權(quán)限訪問(wèn)該資源,如果有則放行;如果沒(méi)有則返回拒絕訪問(wèn)的通知。

那么我們?nèi)绾闻袛嘣撚脩羰欠裼袡?quán)限訪問(wèn)呢?
這就要求我們?cè)谟脩舻卿浀臅r(shí)候保存其登錄狀態(tài)。

可我們知道http請(qǐng)求是無(wú)狀態(tài)的,即這次請(qǐng)求無(wú)法知道上一次請(qǐng)求的內(nèi)容,那如何保存這個(gè)登錄狀態(tài)呢?

這就需要要用到Session/Cookie機(jī)制(這里我就不多介紹了,感興趣的可以去百度,當(dāng)然我在手把手教你用Java實(shí)現(xiàn)一套簡(jiǎn)單的鑒權(quán)服務(wù)(SpringBoot,SSM)(萬(wàn)字長(zhǎng)文)這篇博文中說(shuō)的很詳細(xì)了,感興趣的同學(xué)可以去看看)。

既然如此,那么我們?cè)诘卿洺晒Φ臅r(shí)候就把用戶的信息存入到服務(wù)器的session中,等用戶下次訪問(wèn)的時(shí)候,我們就知道是哪位用戶以及這位用戶有沒(méi)有權(quán)限訪問(wèn)了。

至此我們便實(shí)現(xiàn)了簡(jiǎn)單的權(quán)限控制。

但是這里有個(gè)地方需要注意,就是過(guò)濾器在攔截時(shí)需要排除一些路徑,比如登錄頁(yè)面,比如靜態(tài)資源。這個(gè)有很多方法,我采取的是我認(rèn)為比較簡(jiǎn)單的方法,具體實(shí)現(xiàn)在下文。

2.代碼實(shí)現(xiàn)

①登錄頁(yè)面

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>后臺(tái)管理-登陸</title>
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta http-equiv="Access-Control-Allow-Origin" content="*">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="format-detection" content="telephone=no">
    <link rel="stylesheet" href="/static/lib/layui-v2.6.3/css/layui.css" rel="external nofollow"  media="all">
    <!--[if lt IE 9]>
    <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
    <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
    <style>
        .main-body {top:50%;left:50%;position:absolute;-webkit-transform:translate(-50%,-50%);-moz-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);-o-transform:translate(-50%,-50%);transform:translate(-50%,-50%);overflow:hidden;}
        .login-main .login-bottom .center .item input {display:inline-block;width:227px;height:22px;padding:0;position:absolute;border:0;outline:0;font-size:14px;letter-spacing:0;}
        .login-main .login-bottom .center .item .icon-1 {background:url(../static/images/icon-login.png) no-repeat 1px 0;}
        .login-main .login-bottom .center .item .icon-2 {background:url(../static/images/icon-login.png) no-repeat -54px 0;}
        .login-main .login-bottom .center .item .icon-3 {background:url(../static/images/icon-login.png) no-repeat -106px 0;}
        .login-main .login-bottom .center .item .icon-4 {background:url(../static/images/icon-login.png) no-repeat 0 -43px;position:absolute;right:-10px;cursor:pointer;}
        .login-main .login-bottom .center .item .icon-5 {background:url(../static/images/icon-login.png) no-repeat -55px -43px;}
        .login-main .login-bottom .center .item .icon-6 {background:url(../static/images/icon-login.png) no-repeat 0 -93px;position:absolute;right:-10px;margin-top:8px;cursor:pointer;}
        .login-main .login-bottom .tip .icon-nocheck {display:inline-block;width:10px;height:10px;border-radius:2px;border:solid 1px #9abcda;position:relative;top:2px;margin:1px 8px 1px 1px;cursor:pointer;}
        .login-main .login-bottom .tip .icon-check {margin:0 7px 0 0;width:14px;height:14px;border:none;background:url(../static/images/icon-login.png) no-repeat -111px -48px;}
        .login-main .login-bottom .center .item .icon {display:inline-block;width:33px;height:22px;}
        .login-main .login-bottom .center .item {width:288px;height:35px;border-bottom:1px solid #dae1e6;margin-bottom:35px;}
        .login-main {width:428px;position:relative;float:left;}
        .login-main .login-top {height:117px;background-color:#148be4;border-radius:12px 12px 0 0;font-family:SourceHanSansCN-Regular;font-size:30px;font-weight:400;font-stretch:normal;letter-spacing:0;color:#fff;line-height:117px;text-align:center;overflow:hidden;-webkit-transform:rotate(0);-moz-transform:rotate(0);-ms-transform:rotate(0);-o-transform:rotate(0);transform:rotate(0);}
        .login-main .login-top .bg1 {display:inline-block;width:74px;height:74px;background:#fff;opacity:.1;border-radius:0 74px 0 0;position:absolute;left:0;top:43px;}
        .login-main .login-top .bg2 {display:inline-block;width:94px;height:94px;background:#fff;opacity:.1;border-radius:50%;position:absolute;right:-16px;top:-16px;}
        .login-main .login-bottom {width:428px;background:#fff;border-radius:0 0 12px 12px;padding-bottom:53px;}
        .login-main .login-bottom .center {width:288px;margin:0 auto;padding-top:40px;padding-bottom:15px;position:relative;}
        .login-main .login-bottom .tip {clear:both;height:16px;line-height:16px;width:288px;margin:0 auto;}
        body {background:url(../static/images/loginbg.png) 0% 0% / cover no-repeat;position:static;font-size:12px;}
        input::-webkit-input-placeholder {color:#a6aebf;}
        input::-moz-placeholder {/* Mozilla Firefox 19+ */            color:#a6aebf;}
        input:-moz-placeholder {/* Mozilla Firefox 4 to 18 */            color:#a6aebf;}
        input:-ms-input-placeholder {/* Internet Explorer 10-11 */            color:#a6aebf;}
        input:-webkit-autofill {/* 取消Chrome記住密碼的背景顏色 */            -webkit-box-shadow:0 0 0 1000px white inset !important;}
        html {height:100%;}
        .login-main .login-bottom .tip {clear:both;height:16px;line-height:16px;width:288px;margin:0 auto;}
        .login-main .login-bottom .tip .login-tip {font-family:MicrosoftYaHei;font-size:12px;font-weight:400;font-stretch:normal;letter-spacing:0;color:#9abcda;cursor:pointer;}
        .login-main .login-bottom .tip .forget-password {font-stretch:normal;letter-spacing:0;color:#1391ff;text-decoration:none;position:absolute;right:62px;}
        .login-main .login-bottom .login-btn {width:288px;height:40px;background-color:#1E9FFF;border-radius:16px;margin:24px auto 0;text-align:center;line-height:40px;color:#fff;font-size:14px;letter-spacing:0;cursor:pointer;border:none;}
        .login-main .login-bottom .center .item .validateImg {position:absolute;right:1px;cursor:pointer;height:36px;border:1px solid #e6e6e6;}
        .footer {left:0;bottom:0;color:#fff;width:100%;position:absolute;text-align:center;line-height:30px;padding-bottom:10px;text-shadow:#000 0.1em 0.1em 0.1em;font-size:14px;}
        .padding-5 {padding:5px !important;}
        .footer a,.footer span {color:#fff;}
        @media screen and (max-width:428px) {.login-main {width:360px !important;}
            .login-main .login-top {width:360px !important;}
            .login-main .login-bottom {width:360px !important;}
        }
    </style>
</head>
<body>
<div class="main-body">
    <div class="login-main">
        <div class="login-top">
            <span>LayuiMini后臺(tái)登錄</span>
            <span class="bg1"></span>
            <span class="bg2"></span>
        </div>
        <form class="layui-form login-bottom" action="/login" method="post">
            <div class="center">
                <div class="item">
                    <span class="icon icon-2"></span>
                    <input type="text" name="uname" lay-verify="required"  placeholder="請(qǐng)輸入登錄賬號(hào)" maxlength="24"/>
                </div>

                <div class="item">
                    <span class="icon icon-3"></span>
                    <input type="password" name="pwd" lay-verify="required"  placeholder="請(qǐng)輸入密碼" maxlength="20">
                    <span class="bind-password icon icon-4"></span>
                </div>

            </div>
            <div class="tip">
                <span class="icon-nocheck"></span>
                <span class="login-tip">保持登錄</span>
                <a href="javascript:" rel="external nofollow"  class="forget-password">忘記密碼?</a>
            </div>
            <div class="layui-form-item" >
                <button class="login-btn" type="submit" lay-submit="" lay-filter="login">立即登錄</button>
            </div>
        </form>
    </div>
</div>
<div class="footer">
    &copy;版權(quán)所有 2014-2018 叁貳柒工作室<span class="padding-5">|</span><a target="_blank" href="http://www.miitbeian.gov.cn" rel="external nofollow" >粵ICP備16006642號(hào)-2</a>
</div>
<script src="/static/lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
<script>
    //原本想用json的post發(fā)送,結(jié)果發(fā)現(xiàn)后端數(shù)據(jù)得自己解析,為了降低難度,直接用form表單的post提交,這樣后端直接拿數(shù)據(jù)即可(不然還得解析Json數(shù)據(jù))
    // layui.use(['form','jquery'], function () {
    //     var $ = layui.jquery,
    //         form = layui.form,
    //         layer = layui.layer;
    //
    //     // 登錄過(guò)期的時(shí)候,跳出ifram框架
    //     if (top.location != self.location) top.location = self.location;
    //
    //     $('.bind-password').on('click', function () {
    //         if ($(this).hasClass('icon-5')) {
    //             $(this).removeClass('icon-5');
    //             $("input[name='pwd']").attr('type', 'password');
    //         } else {
    //             $(this).addClass('icon-5');
    //             $("input[name='pwd']").attr('type', 'text');
    //         }
    //     });
    //
    //     $('.icon-nocheck').on('click', function () {
    //         if ($(this).hasClass('icon-check')) {
    //             $(this).removeClass('icon-check');
    //         } else {
    //             $(this).addClass('icon-check');
    //         }
    //     });
    //
    //     // 進(jìn)行登錄操作
    //     form.on('submit(login)', function (data) {
    //         data = data.field;
    //         if (data.uname == '') {
    //             layer.msg('用戶名不能為空');
    //             return false;
    //         }
    //         if (data.pwd == '') {
    //             layer.msg('密碼不能為空');
    //             return false;
    //         }
    //         $.ajax({
    //             url:'/login',
    //             method:'post',
    //             data:data,
    //             dataType:'JSON',
    //             success:function(res){
    //                 if (res.msg==='登錄成功'){
    //                     layer.msg('登錄成功', function () {
    //                         window.location = '../index.html';
    //                     });
    //                 }else {
    //                     layer.msg("登錄失敗");
    //                 }
    //             },
    //             error:function (data) {
    //             }
    //         }) ;
    //
    //
    //         return false;
    //     });
    // });
</script>
</body>
</html>

因?yàn)樯厦嫖也](méi)有給出圖片,css等靜態(tài)資源,所以直接復(fù)制是沒(méi)有我這里的效果的。

下面這樣也是可以的,

<!DOCTYPE html>
<htmllang="en">
<head>
    <meta charset="UTF-8">
    <title>用戶登錄</title>
</head>
<body>
<form action="/login" method="post">
    用戶名:<input type="text" name="uname">
    密碼:<input type="password" name="pwd">
    <input type="submit" value="login">
</form>
 
</body>
</html>

②登錄Servlet類

具體驗(yàn)證的邏輯我這里就不放了。這里登錄成功會(huì)將用戶名存入session,并自動(dòng)跳轉(zhuǎn)首頁(yè)。

package com.dreamchaser.loginTest.servlet;

import com.dreamchaser.loginTest.mapper.UserMapper;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class LoginServlet extends HttpServlet {
    static UserMapper userMapper=UserMapper.getUserMapper();

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String uname=req.getParameter("uname");
        String pwd=req.getParameter("pwd");
        ServletOutputStream outputStream = resp.getOutputStream();
        String result;
        if (pwd.equals(userMapper.getPwdByName(uname))){
            req.getSession().setAttribute("user",uname);
            resp.sendRedirect("/index.html");
        }else {
            //響應(yīng)
            result="登錄失敗";
            outputStream.write(result.getBytes());
        }
    }
}

③UserFilter過(guò)濾器

因?yàn)樵撨^(guò)濾器配置的路徑是/*,即全部路徑,但是我們不想攔截一些路徑,比如登錄頁(yè)面,靜態(tài)資源,所以我們?cè)诓僮髑斑M(jìn)行一次判斷,避免這些路徑的處理。

注:innit方法會(huì)將配置中排除的路徑讀取過(guò)來(lái),當(dāng)然你也可以寫在程序里

package com.dreamchaser.loginTest.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class UserFilter implements Filter {

    private List excludedUrls;

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
            throws IOException, ServletException {
        // 將req resp 轉(zhuǎn)為子接口的類型
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse)resp;
        String path = request.getServletPath();

        if(!excludedUrls.contains(path)&&!(path.length()>8&&"/static/".equals(path.substring(0,8))))
        {
            if (request.getSession().getAttribute("user")==null){
               response.sendRedirect("/pages/login.html");
            }
        }
        chain.doFilter(req, resp);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String excludePattern = filterConfig.getInitParameter("excludedUrls");
        excludedUrls = Arrays.asList(excludePattern.split(","));
    }

    @Override
    public void destroy() {
    }
}

④web.xml配置項(xiàng)

init-param標(biāo)簽里存放的是排除在外的路徑,這個(gè)是自己定義的。

<servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>com.dreamchaser.loginTest.servlet.LoginServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/login</url-pattern>
  </servlet-mapping>

  <filter>
    <filter-name>UserFilter</filter-name>
    <filter-class>com.dreamchaser.loginTest.filter.UserFilter</filter-class>
    <init-param>
      <param-name>excludedUrls</param-name>
      <param-value>/pages/login.html,/register.html,/login</param-value>
    </init-param>

  </filter>
  <filter-mapping>
    <filter-name>UserFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

二、敏感詞過(guò)濾

1.思路

利用過(guò)濾器提前對(duì)請(qǐng)求里要過(guò)濾的屬性進(jìn)行處理,但是因?yàn)闆](méi)有setParameter方法(這是故意的,設(shè)計(jì)者就是不想讓我們直接修改),所以我們?yōu)榱舜娣胚^(guò)濾后的信息,可以把過(guò)濾后的信息放在attribute中,然后servlet直接獲取即可。(當(dāng)然也可以重寫一個(gè)Request類,那個(gè)比較麻煩,感興趣的自行百度)

2.代碼實(shí)現(xiàn)

①敏感詞過(guò)濾頁(yè)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/word" method="post" >
        請(qǐng)輸入你要說(shuō)的垃圾話:<br><input name="word"  type="text">
        <button type="submit"> 提交</button>
    </form>
</body>
</html>

②WordServlet類

從attribute中獲取過(guò)濾后的字符串后返回。

package com.dreamchaser.loginTest.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 需要敏感詞過(guò)濾的接口
 */
public class WordServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //因?yàn)閟ervlet并沒(méi)有setParameter方法(這是故意的),所以過(guò)濾后word無(wú)法通過(guò)getparameter來(lái)獲取
        //所以一般有兩種方法一種把它放在attribute里,一種重寫Request類,不過(guò)這會(huì)很麻煩
        String word= String.valueOf(req.getAttribute("word"));
        ServletOutputStream outputStream = resp.getOutputStream();
        String result="詞匯已凈化,請(qǐng)放心食用:"+word;
        outputStream.write(result.getBytes());
    }
}

③WordFilter過(guò)濾器類

靜態(tài)常量sensitiveWords中存放的是需要過(guò)濾的字符串,harmoniousWord是過(guò)濾后的詞匯。
這里就是對(duì)需要過(guò)濾的借口提前進(jìn)行處理,把敏感詞換成注入“***”這樣的字符串,然后存放在attribute中。

package com.dreamchaser.loginTest.filter;


import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 敏感詞過(guò)濾攔截器
 */
public class WordFilter implements Filter {
    static final String[] sensitiveWords={"敏感詞1","臟話","罵人"};
    static final String harmoniousWord="***";

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        req.setCharacterEncoding("utf-8");
        // 將req resp 轉(zhuǎn)為子接口的類型
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse)resp;
        String word=req.getParameter("word");
        for (String s:sensitiveWords){
            word=word.replaceAll(s,harmoniousWord);
        }
        request.setAttribute("word",word);
        chain.doFilter(req, resp);
    }
}

web.xml配置項(xiàng)

<servlet>
    <servlet-name>WordServlet</servlet-name>
    <servlet-class>com.dreamchaser.loginTest.servlet.WordServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>WordServlet</servlet-name>
    <url-pattern>/word</url-pattern>
  </servlet-mapping>

  <filter>
    <filter-name>WordFilter</filter-name>
    <filter-class>com.dreamchaser.loginTest.filter.WordFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>WordFilter</filter-name>
    <url-pattern>/word</url-pattern>
  </filter-mapping>

三、效果展示

1.未登錄訪問(wèn)其他資源

自動(dòng)跳轉(zhuǎn)至登錄頁(yè)

servlet如果實(shí)現(xiàn)簡(jiǎn)單的權(quán)限管理和敏感詞過(guò)濾功能

2.密碼錯(cuò)誤,登錄失敗

servlet如果實(shí)現(xiàn)簡(jiǎn)單的權(quán)限管理和敏感詞過(guò)濾功能

3.密碼正確,自動(dòng)跳轉(zhuǎn)首頁(yè)

servlet如果實(shí)現(xiàn)簡(jiǎn)單的權(quán)限管理和敏感詞過(guò)濾功能

4.刷新首頁(yè),不會(huì)跳轉(zhuǎn)

servlet如果實(shí)現(xiàn)簡(jiǎn)單的權(quán)限管理和敏感詞過(guò)濾功能

5.敏感詞過(guò)濾

servlet如果實(shí)現(xiàn)簡(jiǎn)單的權(quán)限管理和敏感詞過(guò)濾功能

處理后返回結(jié)果

servlet如果實(shí)現(xiàn)簡(jiǎn)單的權(quán)限管理和敏感詞過(guò)濾功能

注:代碼已開源至gitee,地址

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“servlet如果實(shí)現(xiàn)簡(jiǎn)單的權(quán)限管理和敏感詞過(guò)濾功能”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!

向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