目 录CONTENT

文章目录

一种简单的加密文章实现(2)

这一次使用纯粹使用前端来加密内容,优点是部署方便,不用折腾后端和数据库,缺点是加密不灵活,如果要修改密钥需要重新生成密文。

首先是加密代码,为了方便测试,同时加入了解密功能,你可以在本地打开这个html文件使用:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>加密内容查看器</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
    <style>
        body {
            font-family: system-ui, -apple-system, sans-serif;
            margin: 0;
            padding: 20px;
            background: inherit;
        }
        .container {
            width: 100%;
            max-width: 100%;
            padding: 20px;
            box-sizing: border-box;
            background: inherit;
        }
        .section {
            margin-bottom: 30px;
            padding: 20px;
            border: 1px solid #ddd;
            border-radius: 8px;
            background: inherit;
        }
        textarea {
            width: 100%;
            height: 100px;
            margin: 10px 0;
            padding: 8px;
            box-sizing: border-box;
            border: 1px solid #ddd;
            border-radius: 4px;
            background: inherit;
        }
        input {
            padding: 8px 12px;
            border: 1px solid #ddd;
            border-radius: 4px;
            margin-right: 10px;
            font-size: 16px;
            background: inherit;
        }
        button {
            padding: 8px 16px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
        }
        button:hover {
            background-color: #45a049;
        }
        .result {
            margin-top: 20px;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            word-break: break-all;
            background: inherit;
        }
        .error {
            color: #ff4444;
            margin-top: 10px;
        }

        /* 响应式布局 */
        @media screen and (max-width: 768px) {
            body {
                padding: 10px;
            }
            .container {
                padding: 10px;
            }
            .section {
                padding: 15px;
            }
            input {
                width: 100%;
                margin: 10px 0;
            }
            button {
                width: 100%;
                margin: 10px 0;
            }
        }

        /* 超宽屏幕优化 */
        @media screen and (min-width: 1200px) {
            .container {
                max-width: 1200px;
                margin: 0 auto;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <!-- 加密部分 -->
        <div class="section">
            <h3>加密内容</h3>
            <div>
                <textarea id="content-to-encrypt" placeholder="输入要加密的内容"></textarea>
            </div>
            <div>
                <input type="password" id="encrypt-password" placeholder="设置加密密码">
                <button onclick="encryptContent()">加密</button>
            </div>
            <div class="result" id="encrypted-result"></div>
        </div>

        <!-- 解密部分 -->
        <div class="section">
            <h3>解密内容</h3>
            <div>
                <textarea id="content-to-decrypt" placeholder="输入加密后的内容"></textarea>
            </div>
            <div>
                <input type="password" id="decrypt-password" placeholder="输入解密密码">
                <button onclick="decryptContent()">解密</button>
            </div>
            <div id="decrypt-error" class="error"></div>
            <div class="result" id="decrypted-result"></div>
        </div>
    </div>

    <script>
        function encryptContent() {
            const content = document.getElementById('content-to-encrypt').value;
            const password = document.getElementById('encrypt-password').value;
            
            if (!content || !password) {
                alert('请输入内容和密码');
                return;
            }
            try {
                const encrypted = CryptoJS.AES.encrypt(content, password).toString();
                document.getElementById('encrypted-result').textContent = encrypted;
                document.getElementById('content-to-decrypt').value = encrypted;
            } catch (e) {
                alert('加密失败:' + e.message);
            }
        }

        function decryptContent() {
            const encryptedText = document.getElementById('content-to-decrypt').value;
            const password = document.getElementById('decrypt-password').value;
            const errorDiv = document.getElementById('decrypt-error');
            const resultDiv = document.getElementById('decrypted-result');
            
            if (!encryptedText || !password) {
                errorDiv.textContent = '请输入加密内容和密码';
                return;
            }
            try {
                const decrypted = CryptoJS.AES.decrypt(encryptedText, password).toString(CryptoJS.enc.Utf8);
                
                if (decrypted) {
                    resultDiv.textContent = decrypted;
                    errorDiv.textContent = '';
                } else {
                    errorDiv.textContent = '解密失败:密码错误或内容格式不正确';
                    resultDiv.textContent = '';
                }
            } catch (e) {
                errorDiv.textContent = '解密失败:' + e.message;
                resultDiv.textContent = '';
            }
        }

        document.getElementById('decrypt-password').addEventListener('keypress', function(e) {
            if (e.key === 'Enter') {
                decryptContent();
            }
        });
    </script>
</body>
</html>

效果如下:

加密内容查看器

加密内容

解密内容

然后把加密后的密文放入前端中(替换位置在163行,支持markdown渲染):

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>加密文章访问</title>
    
    <!-- 使用 ES6 模块方式加载 marked -->
    <script type="module">
        import { marked } from 'https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js';
        window.marked = marked;
        marked.setOptions({
            breaks: true,
            gfm: true
        });
    </script>
    
    <style>
        body {
            font-family: 'Microsoft YaHei', sans-serif;
            margin: 0;
            padding: 0;
            line-height: 1.6;
            min-height: 100vh;
            display: flex;
            justify-content: center;
        }
        
        .container {
            width: 100%;
            max-width: 100%;
            padding: clamp(15px, 3vw, 30px);
            margin: 0 auto;
            background: inherit;
        }
        
        .password-section {
            max-width: 600px;
            margin: 20px auto;
            padding: 20px;
            text-align: center;
            background: inherit;
        }
        
        input[type="password"] {
            padding: 8px 12px;
            border: 1px solid #ddd;
            border-radius: 4px;
            width: 200px;
            margin-right: 10px;
            background: inherit;
        }
        
        button {
            padding: 8px 16px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        
        button:hover {
            filter: brightness(90%);
        }
        
        .error-message {
            color: #dc3545;
            margin-top: 10px;
            display: none;
        }
        
        .article-content {
            width: 100%;
            max-width: 100%;
            padding: 0 max(20px, 5vw);
            box-sizing: border-box;
            opacity: 0;
            display: none;
        }
        
        .article-content.visible {
            opacity: 1;
            display: block;
            transition: opacity 0.5s ease;
        }
        
        .markdown-content {
            width: 100%;
            max-width: 100%;
            margin: 0 auto;
            line-height: 1.8;
        }
        
        @media screen and (max-width: 768px) {
            .container {
                padding: 10px;
            }
            
            input[type="password"], button {
                width: 100%;
                max-width: 300px;
                margin: 10px 0;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <div id="passwordSection" class="password-section">
            <input type="password" id="passwordInput" placeholder="请输入密码">
            <button onclick="verifyPassword()">验证密码</button>
            <div id="errorMessage" class="error-message"></div>
        </div>
        <div id="articleContent" class="article-content">
            <div id="articleBody" class="markdown-content"></div>
        </div>
    </div>

    <script>
        function showError(message) {
            const errorElement = document.getElementById('errorMessage');
            errorElement.textContent = message;
            errorElement.style.display = 'block';
            
            setTimeout(() => {
                errorElement.style.display = 'none';
            }, 3000);
            
            if (message.includes('密码错误')) {
                const passwordInput = document.getElementById('passwordInput');
                passwordInput.value = '';
                passwordInput.focus();
            }
        }

        function showArticle(content) {
            const passwordSection = document.getElementById('passwordSection');
            passwordSection.style.display = 'none';
            
            try {
                const articleBody = document.getElementById('articleBody');
                if (typeof window.marked === 'undefined') {
                    articleBody.textContent = content;
                } else {
                    articleBody.innerHTML = window.marked.parse(content);
                }
            } catch (error) {
                console.error('Markdown 渲染错误:', error);
                document.getElementById('articleBody').textContent = content;
            }
            
            const articleContent = document.getElementById('articleContent');
            articleContent.style.display = 'block';
            setTimeout(() => {
                articleContent.classList.add('visible');
            }, 10);
        }

        function verifyPassword() {
            const password = document.getElementById('passwordInput').value;
            // 这里替换为你的加密内容和验证逻辑
            const encryptedContent = "你的加密内容";
            
            try {
                const decrypted = CryptoJS.AES.decrypt(encryptedContent, password).toString(CryptoJS.enc.Utf8);
                if (decrypted) {
                    showArticle(decrypted);
                } else {
                    showError('密码错误,请重试');
                }
            } catch (e) {
                showError('密码错误,请重试');
            }
        }

        document.getElementById('passwordInput').addEventListener('keypress', function(e) {
            if (e.key === 'Enter') {
                verifyPassword();
            }
        });
    </script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
</body>
</html>

效果演示(密码2025):

加密文章访问

0

评论区