nacos源码修改编译

文章目录

  • nacos源码修改编译
    • 内容概述
    • 源码修改
    • 源码编译
    • 测试

内容概述

生产项目选型时选择nacos作为项目的注册中心,但是由于内网安全要求,用户名和密码必须加密传输,故此更改nacos源码进行编译使用。

源码修改

首先从仓库下载nacos的源码,地址为:https://github.com/alibaba/nacos
下载之后的内容我们需要修改前端代码以及后端代码,前端将用户名和密码进行编码之后传递到后台,后台接收到参数后进行解码操作,本文使用的加密算法为非对称加密算法RSA。

  1. 前端内容修改

修改文件:C:\Users\Administrator\Desktop\nacos-2.0.4\console-ui\src\pages\Login\Login.jsx

/** Copyright 1999-2018 Alibaba Group Holding Ltd.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
/*** 新增内容*/
/* eslint-disable */
import React from 'react';
import {Card, Form, Input, Message, ConfigProvider, Field} from '@alifd/next';
import {withRouter} from 'react-router-dom';import './index.scss';
import Header from '../../layouts/Header';
import PropTypes from 'prop-types';
import {login} from '../../reducers/base';
/*** 新增内容*/
import {JSEncrypt} from 'jsencrypt';const FormItem = Form.Item;@withRouter
@ConfigProvider.config
class Login extends React.Component {static displayName = 'Login';static propTypes = {locale: PropTypes.object,history: PropTypes.object,};constructor(props) {super(props);this.field = new Field(this);}componentDidMount() {if (localStorage.getItem('token')) {const [baseUrl] = location.href.split('#');location.href = `${baseUrl}#/`;}}handleSubmit = () => {/*** 新增内容*/let encrypt = new JSEncrypt();/*** 新增内容*/encrypt.setPublicKey('MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6a5ZRaBn5earnUBI7tQIWNZUvqim/iZUhb2PLSY+kcUVcKuguWTqsUqdyHvYofK0oYNrAwUUGqiSyNwMl5NPg/Rc60m1RAKERl+bP3ZEyyhS1/jzVe7yQ7WuYrtYF8nk70b9iHwOJABJMNYarWWq4eT1vd81zoBENRXqV3yEhlQIDAQAB');const {locale = {}} = this.props;this.field.validate((errors, values) => {if (errors) {return;}/*** 新增内容*/let authstring = values.username + ":::" + values.password;let requestData = {authstring: encrypt.encrypt(authstring)};/*** 修改内容*/// const { locale = {} } = this.props;// this.field.validate((errors, values) => {//   if (errors) {//     return;//   }login(requestData).then(res => {localStorage.setItem('token', JSON.stringify(res));this.props.history.push('/');}).catch(() => {Message.error({content: locale.invalidUsernameOrPassword,});});});};onKeyDown = event => {// 'keypress' event misbehaves on mobile so we track 'Enter' key via 'keydown' eventif (event.key === 'Enter') {event.preventDefault();event.stopPropagation();this.handleSubmit();}};render() {const {locale = {}} = this.props;return (<div className="home-page"><Header/><sectionclassName="top-section"style={{background: 'url(img/black_dot.png) repeat',backgroundSize: '14px 14px',}}><div className="vertical-middle product-area"><img className="product-logo" src="img/nacos.png"/><p className="product-desc">an easy-to-use dynamic service discovery, configuration and service managementplatform for building cloud native applications</p></div><div className="animation animation1"/><div className="animation animation2"/><div className="animation animation3"/><div className="animation animation4"/><div className="animation animation5"/><Card className="login-panel" contentHeight="auto"><div className="login-header">{locale.login}</div><div className="internal-sys-tip"><div>{locale.internalSysTip1}</div><div>{locale.internalSysTip2}</div></div><Form className="login-form" field={this.field}><FormItem><Input{...this.field.init('username', {rules: [{required: true,message: locale.usernameRequired,},],})}placeholder={locale.pleaseInputUsername}onKeyDown={this.onKeyDown}/></FormItem><FormItem><InputhtmlType="password"placeholder={locale.pleaseInputPassword}{...this.field.init('password', {rules: [{required: true,message: locale.passwordRequired,},],})}onKeyDown={this.onKeyDown}/></FormItem><FormItem label=" "><Form.Submit onClick={this.handleSubmit}>{locale.submit}</Form.Submit></FormItem></Form></Card></section></div>);}
}export default Login;

修改文件:C:\Users\Administrator\Desktop\nacos-2.0.4\console-ui\package.json

{"name": "console-ui","version": "1.0.0","description": "console ui","main": "index.js","scripts": {"start": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.dev.conf.js","build": "cross-env NODE_ENV=production webpack --config build/webpack.prod.conf.js && node build/copyFile.js","eslint": "eslint --ext .js src/","eslint-fix": "eslint  --ext .js --fix src/"},"husky": {"hooks": {"pre-commit": "lint-staged"}},"lint-staged": {"*.{js,css,less}": ["prettier --write","git add"]},"license": "Apache-2.0","repository": {"type": "git","url": "git+https://github.com/alibaba/nacos.git"},"devDependencies": {"@alifd/next-theme-loader": "^1.3.1","@babel/cli": "^7.7.7","@babel/core": "^7.7.7","@babel/plugin-proposal-decorators": "^7.7.4","@babel/preset-env": "^7.7.7","@babel/runtime": "^7.7.7","babel-eslint": "^10.0.1","babel-loader": "^8.0.4","babel-plugin-import": "^1.13.0","babel-preset-react-app": "^9.1.0","clean-webpack-plugin": "^3.0.0","copy-webpack-plugin": "^5.1.1 ","cross-env": "^6.0.3","css-loader": "^3.4.0","eslint": "^6.8.0","eslint-config-ali": "^9.0.2","eslint-config-prettier": "^6.8.0","eslint-loader": "^3.0.3","eslint-plugin-import": "^2.14.0","eslint-plugin-prettier": "^3.0.0","eslint-plugin-react": "^7.17.0","eslint-plugin-react-hooks": "^2.3.0","file-loader": "^5.0.2","html-webpack-plugin": "^3.2.0","husky": "^3.1.0","lint-staged": "^9.5.0","mini-css-extract-plugin": "^0.9.0","node-sass": "^4.13.0","optimize-css-assets-webpack-plugin": "^5.0.3","prettier": "1.19.1","sass-loader": "^8.0.0","style-loader": "^1.1.2","uglifyjs-webpack-plugin": "^2.2.0","url-loader": "^3.0.0","webpack": "^4.43.0","webpack-cli": "^3.3.12","webpack-dev-server": "^3.11.0"},"dependencies": {"@alifd/next": "^1.17.4","axios": "^0.21.1","core-js": "2","jsencrypt": "^3.0.0-rc.1","moment": "^2.23.0","qs": "^6.8.2","prop-types": "^15.6.2","react": "^16.12.0","react-dom": "^16.12.0","react-redux": "^7.1.3","react-router": "^5.1.2","react-router-dom": "^5.1.2","react-router-redux": "^4.0.8","redux": "^4.0.5","redux-thunk": "^2.3.0","yamljs": "^0.3.0"}
}
    "core-js": "2","jsencrypt": "^3.0.0-rc.1",
  1. 后端内容修改

新增文件:C:\Users\Administrator\Desktop\nacos-2.0.4\console\src\main\java\com\alibaba\nacos\console\utils\RsaCoder.java

package com.alibaba.nacos.console.utils;import org.apache.commons.codec.binary.Base64;import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;/*** RsaCoder encoder tool** @author twosoy*/
public class RsaCoder {public static final String KEY_ALGORITHM = "RSA";public static final String SIGNATURE_ALGORITHM = "MD5withRSA";private static final String PUBLIC_KEY = "nacosplc";private static final String PRIVATE_KEY = "nacospri";public static byte[] decryptBASE64(String key) {return Base64.decodeBase64(key);}public static String encryptBASE64(byte[] bytes) {return Base64.encodeBase64String(bytes);}/*** 用私钥对信息生成数字签名** @param data       加密数据* @param privateKey 私钥* @return* @throws Exception*/public static String sign(byte[] data, String privateKey) throws Exception {// 解密由base64编码的私钥byte[] keyBytes = decryptBASE64(privateKey);// 构造PKCS8EncodedKeySpec对象PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);// 取私钥匙对象PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);// 用私钥对信息生成数字签名Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);signature.initSign(priKey);signature.update(data);return encryptBASE64(signature.sign());}/*** 校验数字签名** @param data      加密数据* @param publicKey 公钥* @param sign      数字签名* @return 校验成功返回true 失败返回false* @throws Exception*/public static boolean verify(byte[] data, String publicKey, String sign)throws Exception {// 解密由base64编码的公钥byte[] keyBytes = decryptBASE64(publicKey);// 构造X509EncodedKeySpec对象X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);// 取公钥匙对象PublicKey pubKey = keyFactory.generatePublic(keySpec);Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);signature.initVerify(pubKey);signature.update(data);// 验证签名是否正常return signature.verify(decryptBASE64(sign));}public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception{// 对密钥解密byte[] keyBytes = decryptBASE64(key);// 取得私钥PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);// 对数据解密Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, privateKey);return cipher.doFinal(data);}/*** 解密<br>* 用私钥解密** @param data* @param key* @return* @throws Exception*/public static byte[] decryptByPrivateKey(String data, String key)throws Exception {return decryptByPrivateKey(decryptBASE64(data),key);}/*** 解密<br>* 用公钥解密** @param data* @param key* @return* @throws Exception*/public static byte[] decryptByPublicKey(byte[] data, String key)throws Exception {// 对密钥解密byte[] keyBytes = decryptBASE64(key);// 取得公钥X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key publicKey = keyFactory.generatePublic(x509KeySpec);// 对数据解密Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, publicKey);return cipher.doFinal(data);}/*** 加密<br>* 用公钥加密** @param data* @param key* @return* @throws Exception*/public static byte[] encryptByPublicKey(String data, String key)throws Exception {// 对公钥解密byte[] keyBytes = decryptBASE64(key);// 取得公钥X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key publicKey = keyFactory.generatePublic(x509KeySpec);// 对数据加密Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, publicKey);return cipher.doFinal(data.getBytes());}/*** 加密<br>* 用私钥加密** @param data* @param key* @return* @throws Exception*/public static byte[] encryptByPrivateKey(byte[] data, String key)throws Exception {// 对密钥解密byte[] keyBytes = decryptBASE64(key);// 取得私钥PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);// 对数据加密Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, privateKey);return cipher.doFinal(data);}/*** 取得私钥** @param keyMap* @return* @throws Exception*/public static String getPrivateKey(Map<String, Key> keyMap)throws Exception {Key key = (Key) keyMap.get(PRIVATE_KEY);return encryptBASE64(key.getEncoded());}/*** 取得公钥** @param keyMap* @return* @throws Exception*/public static String getPublicKey(Map<String, Key> keyMap)throws Exception {Key key = keyMap.get(PUBLIC_KEY);return encryptBASE64(key.getEncoded());}/*** 初始化密钥** @return* @throws Exception*/public static Map<String, Key> initKey() throws Exception {KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);keyPairGen.initialize(1024);KeyPair keyPair = keyPairGen.generateKeyPair();Map<String, Key> keyMap = new HashMap(2);keyMap.put(PUBLIC_KEY, keyPair.getPublic());keyMap.put(PRIVATE_KEY, keyPair.getPrivate());return keyMap;}/*** 生成公钥和私钥* @param args* @throws Exception*/public static void main(String[] args) throws Exception {Map<String, Key> keyMap = RsaCoder.initKey();String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6a5ZRaBn5earnUBI7tQIWNZUvqim/iZUhb2PLSY+kcUVcKuguWTqsUqdyHvYofK0oYNrAwUUGqiSyNwMl5NPg/Rc60m1RAKERl+bP3ZEyyhS1/jzVe7yQ7WuYrtYF8nk70b9iHwOJABJMNYarWWq4eT1vd81zoBENRXqV3yEhlQIDAQAB";String privateKey = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALprllFoGfl5qudQEju1AhY1lS+qKb+JlSFvY8tJj6RxRVwq6C5ZOqxSp3Ie9ih8rShg2sDBRQaqJLI3AyXk0+D9FzrSbVEAoRGX5s/dkTLKFLX+PNV7vJDta5iu1gXyeTvRv2IfA4kAEkw1hqtZarh5PW93zXOgEQ1FepXfISGVAgMBAAECgYB48goxQJ/xel1F+24I7LOw4wyqQvUY/lMRwSn2nwAhiRed53yBbYSifnGCmdHMjK7vDn9+JSX6X/K06PoS4LYRG6WZ1+kPp6BJHcReOfg6ILFFzYXpUksf07tJDACBt0orG1tAuXBFzoyhZR6PJ61PGiqL58J2YdzlNTGSIzYh9QJBAOGk5th/bjocVECGRXeCbXadVksSabifiuF5z6IuAqdXNEG7ADyBrnpzAN/FibVdkK5Nwy6dVr752Z13+e9Jbr8CQQDTf9RvDZy8qCApN+yQ/t6C/g0MCn/YsHqu5dRM97G/nN1Bys+FJGJ3r/jq0ATwJV3Ww2UzuLBKn0jJ9P54HdirAkEAotDzRXrF1aaFYL3COFbjl3g2QRs7L93nP4U+vl6GyarR6S//HqnQdUiwc8c886Jc+HjiAqvDYTA1xztAHFqXTwJBAKWHOl/gK3eLrgAUgNXKY6Pp6ZQu83hIRvxzbAEBKuBoiNJhRKFTpK0/0HUWcYbx98uKCb69IVyF5ZYKZM7lrRkCQQDfqMQpuXGDdrXIJ4jKgyJEd0zAakdGGjJEd7y+VV4CBvGgaVtWTZgxd+f5vV/PDJyR5AnqcaShqt8HwtP4iyUh";byte[] decodedData = RsaCoder.decryptByPrivateKey("UDYi7GGzuVqkOi5I2MCfZmAn2or2FYwzxbzCeErCuASlIZ1TI+bAvArl5c0VH31FpJsF/xNxCmBdvZzegGH+Sq4NfSneyIEe3ElzixmVAeki4xxkX63sQRur1FivTyhwUV+8HtapGmMjqK5Q+Ke8NQD63422Ir6KMY7vMastCDA=",privateKey);String outputStr = new String(decodedData);System.err.println("加密前: " + "hahah" + "\n\r" + "解密后: " + outputStr);}
}

修改文件:C:\Users\Administrator\Desktop\nacos-2.0.4\console\src\main\java\com\alibaba\nacos\console\controller\UserController.java

/** Copyright 1999-2018 Alibaba Group Holding Ltd.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package com.alibaba.nacos.console.controller;import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.auth.annotation.Secured;
import com.alibaba.nacos.auth.common.ActionTypes;
import com.alibaba.nacos.auth.common.AuthConfigs;
import com.alibaba.nacos.auth.common.AuthSystemTypes;
import com.alibaba.nacos.auth.exception.AccessException;
import com.alibaba.nacos.common.model.RestResult;
import com.alibaba.nacos.common.model.RestResultUtils;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.config.server.auth.RoleInfo;
import com.alibaba.nacos.config.server.model.User;
import com.alibaba.nacos.config.server.utils.RequestUtil;
import com.alibaba.nacos.console.security.nacos.JwtTokenManager;
import com.alibaba.nacos.console.security.nacos.NacosAuthConfig;
import com.alibaba.nacos.console.security.nacos.NacosAuthManager;
import com.alibaba.nacos.console.security.nacos.roles.NacosRoleServiceImpl;
import com.alibaba.nacos.console.security.nacos.users.NacosUser;
import com.alibaba.nacos.console.security.nacos.users.NacosUserDetailsServiceImpl;
import com.alibaba.nacos.console.utils.PasswordEncoderUtil;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.nacos.console.utils.RsaCoder;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Objects;/*** User related methods entry.** @author wfnuser* @author nkorange*/
@RestController("user")
@RequestMapping({"/v1/auth", "/v1/auth/users"})
public class UserController {@Autowiredprivate JwtTokenManager jwtTokenManager;@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate NacosUserDetailsServiceImpl userDetailsService;@Autowiredprivate NacosRoleServiceImpl roleService;@Autowiredprivate AuthConfigs authConfigs;@Autowiredprivate NacosAuthManager authManager;private String privateKey = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALprllFoGfl5qudQEju1AhY1lS+qKb+JlSFvY8tJj6RxRVwq6C5ZOqxSp3Ie9ih8rShg2sDBRQaqJLI3AyXk0+D9FzrSbVEAoRGX5s/dkTLKFLX+PNV7vJDta5iu1gXyeTvRv2IfA4kAEkw1hqtZarh5PW93zXOgEQ1FepXfISGVAgMBAAECgYB48goxQJ/xel1F+24I7LOw4wyqQvUY/lMRwSn2nwAhiRed53yBbYSifnGCmdHMjK7vDn9+JSX6X/K06PoS4LYRG6WZ1+kPp6BJHcReOfg6ILFFzYXpUksf07tJDACBt0orG1tAuXBFzoyhZR6PJ61PGiqL58J2YdzlNTGSIzYh9QJBAOGk5th/bjocVECGRXeCbXadVksSabifiuF5z6IuAqdXNEG7ADyBrnpzAN/FibVdkK5Nwy6dVr752Z13+e9Jbr8CQQDTf9RvDZy8qCApN+yQ/t6C/g0MCn/YsHqu5dRM97G/nN1Bys+FJGJ3r/jq0ATwJV3Ww2UzuLBKn0jJ9P54HdirAkEAotDzRXrF1aaFYL3COFbjl3g2QRs7L93nP4U+vl6GyarR6S//HqnQdUiwc8c886Jc+HjiAqvDYTA1xztAHFqXTwJBAKWHOl/gK3eLrgAUgNXKY6Pp6ZQu83hIRvxzbAEBKuBoiNJhRKFTpK0/0HUWcYbx98uKCb69IVyF5ZYKZM7lrRkCQQDfqMQpuXGDdrXIJ4jKgyJEd0zAakdGGjJEd7y+VV4CBvGgaVtWTZgxd+f5vV/PDJyR5AnqcaShqt8HwtP4iyUh";/*** Create a new user.** @param username username* @param password password* @return ok if create succeed* @throws IllegalArgumentException if user already exist* @since 1.2.0*/@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.WRITE)@PostMappingpublic Object createUser(@RequestParam String username, @RequestParam String password) {User user = userDetailsService.getUserFromDatabase(username);if (user != null) {throw new IllegalArgumentException("user '" + username + "' already exist!");}userDetailsService.createUser(username, PasswordEncoderUtil.encode(password));return RestResultUtils.success("create user ok!");}/*** Delete an existed user.** @param username username of user* @return ok if deleted succeed, keep silent if user not exist* @since 1.2.0*/@DeleteMapping@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.WRITE)public Object deleteUser(@RequestParam String username) {List<RoleInfo> roleInfoList = roleService.getRoles(username);if (roleInfoList != null) {for (RoleInfo roleInfo : roleInfoList) {if (roleInfo.getRole().equals(NacosRoleServiceImpl.GLOBAL_ADMIN_ROLE)) {throw new IllegalArgumentException("cannot delete admin: " + username);}}}userDetailsService.deleteUser(username);return RestResultUtils.success("delete user ok!");}/*** Update an user.** @param username    username of user* @param newPassword new password of user* @param response http response* @param request http request* @return ok if update succeed* @throws IllegalArgumentException if user not exist or oldPassword is incorrect* @since 1.2.0*/@PutMapping@Secured(resource = NacosAuthConfig.UPDATE_PASSWORD_ENTRY_POINT, action = ActionTypes.WRITE)public Object updateUser(@RequestParam String username, @RequestParam String newPassword,HttpServletResponse response, HttpServletRequest request) throws IOException {// admin or same userif (!hasPermission(username, request)) {response.sendError(HttpServletResponse.SC_FORBIDDEN, "authorization failed!");}User user = userDetailsService.getUserFromDatabase(username);if (user == null) {throw new IllegalArgumentException("user " + username + " not exist!");}userDetailsService.updateUserPassword(username, PasswordEncoderUtil.encode(newPassword));return RestResultUtils.success("update user ok!");}private boolean hasPermission(String username, HttpServletRequest request) {if (!authConfigs.isAuthEnabled()) {return true;}if (Objects.isNull(request.getAttribute(RequestUtil.NACOS_USER_KEY))) {return false;}NacosUser user = (NacosUser) request.getAttribute(RequestUtil.NACOS_USER_KEY);// adminif (user.isGlobalAdmin()) {return true;}// same userreturn user.getUserName().equals(username);}/*** Get paged users.** @param pageNo   number index of page* @param pageSize size of page* @return A collection of users, empty set if no user is found* @since 1.2.0*/@GetMapping@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.READ)public Object getUsers(@RequestParam int pageNo, @RequestParam int pageSize) {return userDetailsService.getUsersFromDatabase(pageNo, pageSize);}/*** Login to Nacos** <p>This methods uses username and password to require a new token.** @param response http response* @param request  http request* @return new token of the user* @throws AccessException if user info is incorrect*/// @PostMapping("/login")// public Object login(@RequestParam String username, @RequestParam String password, HttpServletResponse response,//         HttpServletRequest request) throws AccessException {//     if (AuthSystemTypes.NACOS.name().equalsIgnoreCase(authConfigs.getNacosAuthSystemType()) || AuthSystemTypes.LDAP//             .name().equalsIgnoreCase(authConfigs.getNacosAuthSystemType())) {//         NacosUser user = (NacosUser) authManager.login(request);//         response.addHeader(NacosAuthConfig.AUTHORIZATION_HEADER, NacosAuthConfig.TOKEN_PREFIX + user.getToken());//         ObjectNode result = JacksonUtils.createEmptyJsonNode();//         result.put(Constants.ACCESS_TOKEN, user.getToken());//         result.put(Constants.TOKEN_TTL, authConfigs.getTokenValidityInSeconds());//         result.put(Constants.GLOBAL_ADMIN, user.isGlobalAdmin());//         result.put(Constants.USERNAME, user.getUserName());//         return result;//     }//     // create Authentication class through username and password, the implement class is UsernamePasswordAuthenticationToken//     UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username,//             password);//     try {//         // use the method authenticate of AuthenticationManager(default implement is ProviderManager) to valid Authentication//         Authentication authentication = authenticationManager.authenticate(authenticationToken);//         // bind SecurityContext to Authentication//         SecurityContextHolder.getContext().setAuthentication(authentication);//         // generate Token//         String token = jwtTokenManager.createToken(authentication);//         // write Token to Http header//         response.addHeader(NacosAuthConfig.AUTHORIZATION_HEADER, "Bearer " + token);//         return RestResultUtils.success("Bearer " + token);//     } catch (BadCredentialsException authentication) {//         return RestResultUtils.failed(HttpStatus.UNAUTHORIZED.value(), null, "Login failed");//     }// }@PostMapping("/login")public Object login(@RequestParam String authstring,HttpServletResponse response, HttpServletRequest request) throws AccessException {RestResult<String> rr = new RestResult<String>();int paramsSize = 2;int usernameIndex = 0;int passwordIndex = 1;/*获取一个字符串然后再解码*/byte[] decodedData = new byte[0];try {decodedData = RsaCoder.decryptByPrivateKey(authstring,privateKey);} catch (Exception e) {e.printStackTrace();return RestResultUtils.failed(401, null, "参数验证失败");}String authstringDecode = new String(decodedData);String[] usernameAndPassword = authstringDecode.split(":::");if(usernameAndPassword.length != paramsSize){// rr.setCode(401);// rr.setMessage("参数传递不正确");// return rr;return RestResultUtils.failed(401, null, "参数传递不正确");}// 通过用户名和密码创建一个 Authentication 认证对象,实现类为 UsernamePasswordAuthenticationTokenUsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(usernameAndPassword[usernameIndex],usernameAndPassword[passwordIndex]);try {//通过 AuthenticationManager(默认实现为ProviderManager)的authenticate方法验证 Authentication 对象Authentication authentication = authenticationManager.authenticate(authenticationToken);//将 Authentication 绑定到 SecurityContextSecurityContextHolder.getContext().setAuthentication(authentication);//生成Token
//            String token = jwtTokenUtils.createToken(authentication);String token = jwtTokenManager.createToken(authentication);//将Token写入到Http头部response.addHeader(NacosAuthConfig.AUTHORIZATION_HEADER, "Bearer " + token);rr.setCode(200);rr.setData("Bearer " + token);return rr;} catch (BadCredentialsException authentication) {// rr.setCode(401);// rr.setMessage("Login failed");// return rr;return RestResultUtils.failed(401, null, "登录失败");}}/*** Update password.** @param oldPassword old password* @param newPassword new password* @return Code 200 if update successfully, Code 401 if old password invalid, otherwise 500*/@PutMapping("/password")@Deprecatedpublic RestResult<String> updatePassword(@RequestParam(value = "oldPassword") String oldPassword,@RequestParam(value = "newPassword") String newPassword) {Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();String username = ((UserDetails) principal).getUsername();User user = userDetailsService.getUserFromDatabase(username);String password = user.getPassword();// TODO: throw out more fine grained exceptionstry {if (PasswordEncoderUtil.matches(oldPassword, password)) {userDetailsService.updateUserPassword(username, PasswordEncoderUtil.encode(newPassword));return RestResultUtils.success("Update password success");}return RestResultUtils.failed(HttpStatus.UNAUTHORIZED.value(), "Old password is invalid");} catch (Exception e) {return RestResultUtils.failed(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Update userpassword failed");}}/*** Fuzzy matching username.** @param username username* @return Matched username*/@GetMapping("/search")@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.WRITE)public List<String> searchUsersLikeUsername(@RequestParam String username) {return userDetailsService.findUserLikeUsername(username);}
}

源码编译

  1. 前端编译

使用vscode打开目录: console-ui
cnpm install
cnpm run build
打包完成之后会生成dist文件夹,把dist文件夹下的内容拷贝到上一层目录。

  1. 后端编译

打开目录: nacos-2.0.4
打包命令:mvn -Prelease-nacos -Dmaven.test.skip=true -Dcheckstyle.skip=true -Drat.skip=true -Dpmd.skip=true clean install -U
打包完成之后会在distribution目录下生成target目录,里面的内容就是打包之后的内容。

测试

将打包之后的文件上传到Linux服务器上,进入bin目录执行启动命令:sh startup.sh -m standalone
访问:http://ip:8848/nacos/#/login 输入默认账号密码:nacos,nacos
建议登陆之后及时修改密码,注意密码强度。

以上就是本章节的内容,欢迎各位批评指教。如果需要编译好的文件可以直接访问此链接进行下载:nacos2.0.4版本使用RSA算法加密之后的源码,可以直接使用 。

nacos源码修改编译(亲测)相关推荐

  1. 美丽乡村建设网站php源码_2020最新亲测php网址导航源码全开源-清爽收录导航网站源码...

    2020最新亲测php网址导航源码全开源-清爽收录导航网站源码 一款轻巧.清爽的php源码,已亲测完整可用,运行十分流畅,网页加载非迅速,源码UI设计漂亮,且功能完整.为响应式设计,兼容各种手机移动端 ...

  2. 最新哔哩哔哩视频弹幕播放器源码+带后台/亲测无错误

    正文: 最新哔哩哔哩视频弹幕播放器源码+带后台/亲测无错误,此款播放器源码添加及修复了很多功能,且所有源码均本地化,不存在外链的情况,测试环境:PHP7.0+MySQL5.6 安装教程: 1,访问/d ...

  3. android 4.0模拟器启动不了,Android 4.0 framework源码修改编译,模拟器运行不起来,求助...

    当前位置:编程学习 > wap >> Android 4.0 framework源码修改编译,模拟器运行不起来,求助 我下载编译了android 4.0 ICS的源码,然后能利用编译 ...

  4. 最新转转交易猫闲鱼后台源码+带视频教程亲测

    转转交易猫闲鱼后台源码,功能强大包含了十几种模板游戏等等,免授权 修改数据库账号密码搭建直接使用,亲测可用

  5. 前端加密方法sha256.js源码+用法(亲测可用)

    之前看到一个类似的,但是源码不完整:在此总结一个可用的. 一.sha256.js /**** Secure Hash Algorithm (SHA256)* http://www.webtoolkit ...

  6. thinkphp多城市房产系统源码程序_亲测Thinkphp开源房产程序源码/多城市版房产系统 带手机版+独家教程...

    「亲测」Thinkphp开源房产程序源码/多城市版房产系统 带手机版+独家教程+去授权+独家修复 本套tp房产源码包含:管理总后台.代理后台.用户中心.前台.PC端.手机版等,pc和手机端的数据同步, ...

  7. 最新WIFI分销大师小程序源码+带后端/亲测可用

    正文: 这程序本人实测搭建成功,有需要的朋友自行去体验吧. 大家最近都在找这类的小程序,网上很多下载下来就是缺胳膊少腿的,大家自己清楚,所以我自己花Q,找人高价拿了一个完整版的,百分百能搭建成功. 分 ...

  8. 老黄历小程序源码前端实例(亲测可用)

    介绍: 天牛星异位,败走天狼.日星月辉,雨星宫执事无法.天雷远渡洋江之北,风起云散,贵猿面堂发黑乌云盖顶有不祥之兆,带俺给你算上一挂. 算了,装不下去了,这是一个适合快速上手微信小程序代码,没有网络请 ...

  9. html转盘游戏代码,html5 转盘 例子 附完整源码 有截图 亲测通过

    [实例简介]html5 转盘实例 可直接拿来做 抽奖程序 [实例截图]  [核心代码] var colors = ["#B8D430", "#3AB745", ...

最新文章

  1. Zeal 离线API文档浏览器
  2. redis常用优化及持久化到硬盘
  3. java代码使用Pair元组-运行可以-编译失败
  4. 为Raspberry Pi开发.NET应用程序:第2部分
  5. 100 - k8s源码分析-准备工作
  6. 常去的国外网站一览表
  7. 云时代操作系统路在何方?麒麟信安的踏雪寻梅之道
  8. 计算机视觉 相机成像原理,计算机视觉之相机成像原理与坐标系转换
  9. 如何开启win10自带的五笔输入法,并把字库切换成五笔98版
  10. 墨天轮“高可用架构”干货文档分享(含Oracle、MySQL、PG资料124篇)
  11. laravel文档工具
  12. 豆瓣排名前500的电视剧
  13. 禁用win10系统的Cortana小娜进程,笔记本散热风扇冷静了
  14. Deepin安装向日葵报错
  15. 哈希函数(hash函数)
  16. 设计模式 - 创建型模式_工厂方法模式
  17. 删除文件过一会又回来_手机文件误删除如何恢复?教你实用的找回方法!
  18. 综合布线中的配线架与理线架
  19. 回溯法求地图填色实验(剪枝)
  20. Apache CXF框架简介

热门文章

  1. 移动APP测试点、思路分析总结(精炼)
  2. word中查看有多少个分隔符
  3. EPIC平台 国家/地区申述修改经验总结
  4. div上下左右居中方法
  5. 发动机双可变气门正时信号示波器测量
  6. MOS管工作原理,就是这么简单
  7. vr技术与图书馆的结合,碰撞出什么火花呢
  8. 机动应急指挥系统_便携式应急指挥系统
  9. Fujitsu UMPC U1010 发布会
  10. linux shell 网页,Linux上shell命令