strip! return nil

本文纠正了一个关于 Ruby 中字符串 strip! 方法的常见误解。通过示例说明了 strip! 方法如何直接修改原始字符串并返回 nil,而不是返回修改后的字符串。强调了在使用带有感叹号 (!) 的方法时需要注意其副作用。

 

strip!会修改self本身并返回结果。若没有进行删除动作,则返回nil。

 

str =''

str.strip   => ''

str.strip!  => nil

 

原以为str.strip! 也为'' 想当然了,查了手册才知道自己错了 以后应该用赋值的方面来处理带!的方法 ,避免出现在这种错误

 


import base64 import os import secrets import sys from datetime import datetime from functools import wraps import requests from cryptography.fernet import Fernet from flask import ( Flask, flash, g, jsonify, make_response, redirect, render_template, request, url_for, ) from flask_sqlalchemy import SQLAlchemy from sqlalchemy.exc import IntegrityError import hashlib db = SQLAlchemy() class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) password_hash = db.Column(db.String(128), nullable=False) salt = db.Column(db.String(64), nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False) vault_entries = db.relationship('VaultEntry', backref='user', lazy=True, cascade='all, delete-orphan') class VaultEntry(db.Model): id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) label = db.Column(db.String(120), nullable=False) login = db.Column(db.String(120), nullable=False) password_encrypted = db.Column(db.Text, nullable=False) notes = db.Column(db.Text) created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False) def hash_password(password: str, salt: bytes) -> str: data = salt + password.encode('utf-8') for _ in range(50): data = hashlib.sha256(data).digest() return base64.b64encode(data).decode('utf-8') def verify_password(password: str, salt_b64: str, digest: str) -> bool: salt = base64.b64decode(salt_b64.encode('utf-8')) return hash_password(password, salt) == digest def generate_salt() -> bytes: return secrets.token_bytes(16) def create_app() -> Flask: app = Flask(__name__) app.config['SECRET_KEY'] = secrets.token_hex(32) app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL', 'sqlite:///vault.db') app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['SIGN_SERVER'] = os.getenv('SIGN_SERVER', 'http://127.0.0.1:4444/sign') fernet_key = os.getenv('FERNET_KEY') if not fernet_key: raise RuntimeError('Missing FERNET_KEY environment variable. Generate one with `python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"`.') app.config['FERNET_KEY'] = fernet_key db.init_app(app) fernet = Fernet(app.config['FERNET_KEY']) with app.app_context(): db.create_all() if not User.query.first(): salt = secrets.token_bytes(16) password = secrets.token_bytes(32).hex() password_hash = hash_password(password, salt) user = User( id=0, username='admin', password_hash=password_hash, salt=base64.b64encode(salt).decode('utf-8'), ) db.session.add(user) db.session.commit() flag = open('/flag').read().strip() flagEntry = VaultEntry( user_id=user.id, label='flag', login='flag', password_encrypted=fernet.encrypt(flag.encode('utf-8')).decode('utf-8'), notes='This is the flag entry.', ) db.session.add(flagEntry) db.session.commit() def login_required(view_func): @wraps(view_func) def wrapped(*args, **kwargs): uid = request.headers.get('X-User', '0') print(uid) if uid == 'anonymous': flash('Please sign in first.', 'warning') return redirect(url_for('login')) try: uid_int = int(uid) except (TypeError, ValueError): flash('Invalid session. Please sign in again.', 'warning') return redirect(url_for('login')) user = User.query.filter_by(id=uid_int).first() if not user: flash('User not found. Please sign in again.', 'warning') return redirect(url_for('login')) g.current_user = user return view_func(*args, **kwargs) return wrapped @app.route('/') def index(): uid = request.headers.get('X-User', '0') if not uid or uid == 'anonymous': return redirect(url_for('login')) return redirect(url_for('dashboard')) @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'POST': username = request.form.get('username', '').strip() password = request.form.get('password', '') confirm_password = request.form.get('confirm_password', '') if not username or not password: flash('Username and password are required.', 'danger') return render_template('register.html') if password != confirm_password: flash('Passwords do not match.', 'danger') return render_template('register.html') salt = generate_salt() password_hash = hash_password(password, salt) user = User( username=username, password_hash=password_hash, salt=base64.b64encode(salt).decode('utf-8'), ) db.session.add(user) try: db.session.commit() except IntegrityError: db.session.rollback() flash('Username already exists. Please choose another.', 'warning') return render_template('register.html') flash('Registration successful. Please sign in.', 'success') return redirect(url_for('login')) return render_template('register.html') @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form.get('username', '').strip() password = request.form.get('password', '') user = User.query.filter_by(username=username).first() if not user or not verify_password(password, user.salt, user.password_hash): flash('Invalid username or password.', 'danger') return render_template('login.html') r = requests.get(app.config['SIGN_SERVER'], params={'uid': user.id}, timeout=5) if r.status_code != 200: flash('Unable to reach the authentication server. Please try again later.', 'danger') return render_template('login.html') token = r.text.strip() response = make_response(redirect(url_for('dashboard'))) response.set_cookie( 'token', token, httponly=True, secure=app.config.get('SESSION_COOKIE_SECURE', False), samesite='Lax', max_age=12 * 3600, ) return response return render_template('login.html') @app.route('/logout') def logout(): response = make_response(redirect(url_for('login'))) response.delete_cookie('token') flash('Signed out.', 'info') return response @app.route('/dashboard') @login_required def dashboard(): user = g.current_user entries = [ { 'id': entry.id, 'label': entry.label, 'login': entry.login, 'password': fernet.decrypt(entry.password_encrypted.encode('utf-8')).decode('utf-8'), 'notes': entry.notes, 'created_at': entry.created_at, } for entry in user.vault_entries ] return render_template('dashboard.html', username=user.username, entries=entries) @app.route('/passwords/new', methods=['POST']) @login_required def create_password(): user = g.current_user label = request.form.get('label', '').strip() login_value = request.form.get('login', '').strip() password_plain = request.form.get('password', '').strip() notes = request.form.get('notes', '').strip() or None if not label or not login_value or not password_plain: flash('Service name, login, and password are required.', 'danger') return redirect(url_for('dashboard')) encrypted_password = fernet.encrypt(password_plain.encode('utf-8')).decode('utf-8') entry = VaultEntry( user_id=user.id, label=label, login=login_value, password_encrypted=encrypted_password, notes=notes, ) db.session.add(entry) db.session.commit() flash('Password entry saved.', 'success') return redirect(url_for('dashboard')) @app.route('/passwords/<int:entry_id>', methods=['DELETE']) @login_required def delete_password(entry_id: int): user = g.current_user entry = VaultEntry.query.filter_by(id=entry_id, user_id=user.id).first() if not entry: return jsonify({'success': False, 'message': 'Entry not found'}), 404 db.session.delete(entry) db.session.commit() return jsonify({'success': True}) return app if __name__ == '__main__': flask_app = create_app() flask_app.run(host='127.0.0.1', port=5000, debug=False) 解析 package main import ( "crypto/rand" "encoding/hex" "fmt" "log" "net/http" "net/http/httputil" "strings" "time" "github.com/golang-jwt/jwt/v5" "github.com/gorilla/mux" ) var ( SecretKey = hex.EncodeToString(RandomBytes(32)) ) type AuthClaims struct { jwt.RegisteredClaims UID string `json:"uid"` } func RandomBytes(length int) []byte { b := make([]byte, length) if _, err := rand.Read(b); err != nil { return nil } return b } func SignToken(uid string) (string, error) { t := jwt.NewWithClaims(jwt.SigningMethodHS256, AuthClaims{ UID: uid, RegisteredClaims: jwt.RegisteredClaims{ Issuer: "Authorizer", Subject: uid, ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)), IssuedAt: jwt.NewNumericDate(time.Now()), NotBefore: jwt.NewNumericDate(time.Now()), }, }) tokenString, err := t.SignedString([]byte(SecretKey)) if err != nil { return "", err } return tokenString, nil } func GetUIDFromRequest(r *http.Request) string { authHeader := r.Header.Get("Authorization") if authHeader == "" { cookie, err := r.Cookie("token") if err == nil { authHeader = "Bearer " + cookie.Value } else { return "" } } if len(authHeader) <= 7 || !strings.HasPrefix(authHeader, "Bearer ") { return "" } tokenString := strings.TrimSpace(authHeader[7:]) if tokenString == "" { return "" } token, err := jwt.ParseWithClaims(tokenString, &AuthClaims{}, func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) } return []byte(SecretKey), nil }) if err != nil { log.Printf("failed to parse token: %v", err) return "" } claims, ok := token.Claims.(*AuthClaims) if !ok || !token.Valid { log.Printf("invalid token claims") return "" } return claims.UID } func main() { authorizer := &httputil.ReverseProxy{Director: func(req *http.Request) { req.URL.Scheme = "http" req.URL.Host = "127.0.0.1:5000" uid := GetUIDFromRequest(req) log.Printf("Request UID: %s, URL: %s", uid, req.URL.String()) req.Header.Del("Authorization") req.Header.Del("X-User") req.Header.Del("X-Forwarded-For") req.Header.Del("Cookie") if uid == "" { req.Header.Set("X-User", "anonymous") } else { req.Header.Set("X-User", uid) } }} signRouter := mux.NewRouter() signRouter.HandleFunc("/sign", func(w http.ResponseWriter, r *http.Request) { if !strings.HasPrefix(r.RemoteAddr, "127.0.0.1:") { http.Error(w, "Forbidden", http.StatusForbidden) } uid := r.URL.Query().Get("uid") token, err := SignToken(uid) if err != nil { log.Printf("Failed to sign token: %v", err) http.Error(w, "Failed to generate token", http.StatusInternalServerError) return } w.Write([]byte(token)) }).Methods("GET") log.Println("Sign service is running at 127.0.0.1:4444") go func() { if err := http.ListenAndServe("127.0.0.1:4444", signRouter); err != nil { log.Fatal(err) } }() log.Println("Authorizer middleware service is running at :5555") if err := http.ListenAndServe(":5555", authorizer); err != nil { log.Fatal(err) } } 找出flag
10-20
import os import re import json import subprocess import time # ==================== 第一部分:MAC 校验与配置更新 ==================== def validate_mac(mac): """校验 MAC 地址格式是否正确""" pattern = re.compile(r'^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$') return pattern.match(mac.strip().upper()) is not None def update_tddp_config_file(mac, device_id): config_path = '/etc/config/tddp' if not os.path.exists(config_path): print(f"错误:文件 {config_path} 不存在!") return False try: with open(config_path, 'r') as f: lines = f.readlines() except Exception as e: print(f"读取文件 {config_path} 失败:{e}") return False formatted_mac = ":".join(mac.replace('-', ':').split(':')) updated_lines = [] for line in lines: if line.strip().startswith("option macaddr"): updated_lines.append(f"\toption macaddr '{formatted_mac}'\n") elif line.strip().startswith("option deviceId"): updated_lines.append(f"\toption deviceId '{device_id}'\n") else: updated_lines.append(line) try: with open(config_path, 'w') as f: f.writelines(updated_lines) print("/etc/config/tddp 更新成功!") return True except Exception as e: print(f"写入文件 {config_path} 失败:{e}") return False def update_json_file(file_path, update_data): if not os.path.exists(file_path): print(f"错误:文件 {file_path} 不存在!") return False try: with open(file_path, 'r', encoding='utf-8') as f: data = json.load(f) except json.JSONDecodeError: print(f"错误:文件 {file_path} 内容不是有效的 JSON 格式。") return False data.update(update_data) try: with open(file_path, 'w', encoding='utf-8') as f: json.dump(data, f, indent=4) print(f"文件 {file_path} 更新成功!") return True except Exception as e: print(f"写入文件 {file_path} 失败:{e}") return False # ==================== 第二部分:Java 进程清理与服务重启 ==================== def find_and_kill_java_processes(): try: output = subprocess.check_output(['ps', '-ef'], stderr=subprocess.STDOUT, text=True) except subprocess.CalledProcessError as e: print("执行 ps 命令失败:", e) return lines = output.splitlines() target_pids = [] for line in lines: if 'java' in line and ('Central' in line or 'Controller' in line): match = re.match(r'\S+\s+(\d+)', line) if match: pid = match.group(1) target_pids.append(pid) if not target_pids: print("未找到匹配的 Central 或 Controller java 进程。") return for pid in target_pids: try: print(f"正在 kill -9 进程 PID={pid}") subprocess.run(['kill', '-9', pid], check=True) except subprocess.CalledProcessError as e: print(f"kill -9 {pid} 失败:{e}") print("进程清理完成。") time.sleep(3) def start_central(): target_dir = '/opt/tplink/Central/lib/' if not os.path.isdir(target_dir): print("未找到 Central 程序目录,跳过启动。") return try: os.chdir(target_dir) print(f"已进入 Central 目录:{target_dir}") except Exception as e: print(f"无法进入目录 {target_dir}:{e}") return command = [ './central-starter-port-local', '-Djava.home=/opt/tplink/EAPController/lib/', '-XX:ParallelGCThreads=2', '-Xms256m', '-Xmx300m', '-Xmn128m', '-Xss1024k', '-XX:MaxHeapFree=32m', '-XX:StackSize=1024k', '-R:ExpectedEdenSize=160m' ] try: process = subprocess.Popen(command) print(f"Central 程序已启动,PID={process.pid}") except Exception as e: print(f"启动 Central 程序失败:{e}") def start_eap_controller(): target_dir = '/opt/tplink/EAPController/lib/' if not os.path.isdir(target_dir): print("未找到 EAPController 程序目录,跳过启动。") return try: os.chdir(target_dir) print(f"已进入 EAPController 目录:{target_dir}") except Exception as e: print(f"无法进入目录 {target_dir}:{e}") return command = [ './local-starter', '-Djava.home=/opt/tplink/EAPController/lib/', '-XX:ParallelGCThreads=2', '-Xms256m', '-Xmx640m', '-Xmn128m', '-Xss1024k', '-XX:MaxHeapFree=32m', '-XX:StackSize=1024k', '-XX:+VerboseGC', '-Dcom.sun.management.jmxremote.port=1090', '-Dcom.sun.management.jmxremote.ssl=false', '-Dcom.sun.management.jmxremote.authenticate=false', '-Djava.rmi.server.hostname=192.168.0.1', '-R:ExpectedEdenSize=160m' ] try: process = subprocess.Popen(command) print(f"EAPController 程序已启动,PID={process.pid}") except Exception as e: print(f"启动 EAPController 程序失败:{e}") # ==================== 第三部分:更新 cloud_config.cfg 和重启服务 ==================== def update_sef_domain(): config_path = '/etc/cloud_proc/cloud_config.cfg' if not os.path.exists(config_path): print(f"错误:文件 {config_path} 不存在!") return False try: with open(config_path, 'r', encoding='utf-8') as f: config_data = json.load(f) except json.JSONDecodeError as e: print(f"JSON 解析失败:{e}") return False if 'cloud' in config_data and 'sefDomain' in config_data['cloud']: old_value = config_data['cloud']['sefDomain'] config_data['cloud']['sefDomain'] = 'n-device-entry-omada-beta.i.tplinkcloud.com' print(f"成功将 sefDomain 从 {old_value} 更新为 n-device-entry-omada-beta.i.tplinkcloud.com") else: print("错误:配置中未找到 cloud.sefDomain 字段!") return False try: with open(config_path, 'w', encoding='utf-8') as f: json.dump(config_data, f, indent=4) print("配置文件更新成功!") return True except Exception as e: print(f"写入文件失败:{e}") return False def restart_cloud_service(): service_script = "/etc/init.d/zzzcloud_proc" command = [service_script, "restart"] if not os.path.exists(service_script): print(f"错误:服务脚本 {service_script} 不存在!") return False try: result = subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) print("服务重启成功!") print(result.stdout) return True except subprocess.CalledProcessError as e: print("服务重启失败!") print(e.stderr) return False # ==================== 主流程 ==================== def main(): print("=== 开始执行完整流程 ===\n") # 1. 输入 MAC 和 device_id input_mac = input("请输入 MAC 地址(格式:00:2D:0F:72:17:01 或 00-2D-0F-72-17-01):").strip().upper() if not validate_mac(input_mac): print("错误:MAC 地址格式不正确!") return if ':' in input_mac: formatted_input_mac = "-".join(input_mac.split(':')) else: formatted_input_mac = input_mac input_device_id = input("请输入 device_id:").strip() if not input_device_id: print("错误:device_id 不能为空!") return # 2. 更新 tddp 配置和 JSON 文件 update_tddp_config_file(formatted_input_mac, input_device_id) device_info_update = { "model_id": "72123002", "model_version": "2.0", "product_version": "2.0", "product_id": "72123002" } update_json_file('/tmp/sysinfo/device-info.json', device_info_update) update_json_file('/tmp/sysinfo/tddp.json', { "mac": formatted_input_mac, "device_id": input_device_id }) # 3. 清理 Java 进程 find_and_kill_java_processes() # 4. 重启服务 start_central() start_eap_controller() # 5. 更新 sefDomain update_sef_domain() # 6. 重启 zzzcloud_proc restart_cloud_service() print("\n所有操作已完成!") if __name__ == '__main__': main() 仔细阅读代码,转为lua脚本
11-25
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值