Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI登录密码改采用更安全的加密策略及可通过-Dbistoury.ui.register_disabled=true来禁用帐号注册功能 #72

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion bistoury-ui-service-impl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,43 @@
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.64</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.2.13.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
Expand All @@ -50,4 +87,14 @@
</plugins>
</build>

</project>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package qunar.tc.bistoury.ui.security;

import qunar.tc.bistoury.ui.service.impl.UserServiceImpl;

public class PasswordEncoderMain {

public static void main(String[] args) {
String rawPassword = args == null || args.length < 1 ? "admin" : args[0];
String encodePwd = UserServiceImpl.encodePwd(rawPassword);
System.out.println("rawPassword: " + rawPassword + " encodePwd: " + encodePwd);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package qunar.tc.bistoury.ui.service.impl;

import org.springframework.security.crypto.password.PasswordEncoder;

/**
* 此旧为实现,仅为兼容而存在 建议采用默认更安全的加密加密策略,实现需要
* 实在需要,请在SPI定义文件META-INF\services\org.springframework.security.crypto.password.PasswordEncoder中配置此实现类
*
* @author qxo
* @date 2020/01/01
*/
public class PasswordEncoder4OldAESCryptImpl implements PasswordEncoder {
qxo marked this conversation as resolved.
Show resolved Hide resolved

private final AESCryptServiceImpl old = new AESCryptServiceImpl();
qxo marked this conversation as resolved.
Show resolved Hide resolved

@Override
public String encode(CharSequence rawPassword) {
return rawPassword == null ? null : old.encrypt(rawPassword.toString());
}

@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return rawPassword == null ? false : old.encrypt(rawPassword.toString()).equals(encodedPassword);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,26 @@

package qunar.tc.bistoury.ui.service.impl;

import java.util.List;
import java.util.ServiceLoader;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import qunar.tc.bistoury.serverside.configuration.DynamicConfig;
import qunar.tc.bistoury.serverside.configuration.DynamicConfigLoader;
import qunar.tc.bistoury.serverside.configuration.local.LocalDynamicConfig;
import qunar.tc.bistoury.ui.dao.UserDao;
import qunar.tc.bistoury.ui.model.User;
import qunar.tc.bistoury.ui.service.AESCryptService;
import qunar.tc.bistoury.ui.service.UserService;

import javax.annotation.PostConstruct;
import java.util.List;

/**
* @author leix.xie
* @date 2019/7/4 11:00
Expand All @@ -44,12 +47,19 @@ public class UserServiceImpl implements UserService {

private static final Splitter SPLITTER = Splitter.on(",").omitEmptyStrings().trimResults();

private static final PasswordEncoder PASSWORD_ENCODER;
static {
ServiceLoader<PasswordEncoder> sloader = ServiceLoader.load(PasswordEncoder.class);
PASSWORD_ENCODER = sloader.iterator().next();
}

public static String encodePwd(String rawPassword) {
return PASSWORD_ENCODER.encode(rawPassword);
}

qxo marked this conversation as resolved.
Show resolved Hide resolved
@Autowired
private UserDao userDao;

@Autowired
private AESCryptService aesCryptService;

private List<String> admins;

@PostConstruct
Expand All @@ -61,24 +71,42 @@ public void init() {
@Override
public boolean login(User user) {
User checkUser = this.userDao.getUserByUserCode(user.getUserCode());
if (checkUser == null || !this.aesCryptService.encrypt(user.getPassword()).equals(checkUser.getPassword())) {
if (checkUser == null || !PASSWORD_ENCODER.matches(user.getPassword(), checkUser.getPassword())) {
return false;
}
return true;
}

/**
* 为true表示禁止帐号注册功能
*/
private final boolean disable4register = Boolean.getBoolean("bistoury.ui.register_disabled");

@Override
public int register(User user) {
if (disable4register) {
qxo marked this conversation as resolved.
Show resolved Hide resolved
throw new IllegalAccessError("User register is disabled!");
}
Preconditions.checkNotNull(user, "user cannot be null");
Preconditions.checkArgument(!Strings.isNullOrEmpty(user.getUserCode()), "user code cannot be null or empty");
Preconditions.checkArgument(!Strings.isNullOrEmpty(user.getPassword()), "password cannot be null or empty");
User checkUser = this.userDao.getUserByUserCode(user.getUserCode());
if (checkUser != null) {
return -1;
}
user.setPassword(this.aesCryptService.encrypt(user.getPassword()));
user.setPassword(PASSWORD_ENCODER.encode(user.getPassword()));
return this.userDao.registerUser(user);
}

public boolean changePwd(String uid, String oldPwd, String newPwd) {
User checkUser = this.userDao.getUserByUserCode(uid);
if (checkUser == null || !PASSWORD_ENCODER.matches(oldPwd, checkUser.getPassword())) {
return false;
}

int ret = userDao.updatePwd(uid, oldPwd, newPwd);
return ret > 0;
}
qxo marked this conversation as resolved.
Show resolved Hide resolved

@Override
public boolean isAdmin(final String userCode) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
org.springframework.security.crypto.password.Pbkdf2PasswordEncoder
#org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
#org.springframework.security.crypto.scrypt.SCryptPasswordEncoder
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package qunar.tc.bistoury.ui.security;

import org.junit.Assert;
import org.junit.Test;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;

public class PasswordEncoderTest {

@Test
public void test() {
PasswordEncoder[] passwordEncoders = new PasswordEncoder[] {
new Pbkdf2PasswordEncoder(),
new BCryptPasswordEncoder(),
new SCryptPasswordEncoder()
};
final String rawPassword = "password";
for (PasswordEncoder passwordEncoder : passwordEncoders) {
final String encoded = passwordEncoder.encode(rawPassword);
System.out.println(passwordEncoder.getClass()+" src: "+rawPassword + " => "+encoded);
Assert.assertTrue(passwordEncoder.matches(rawPassword, encoded));
}
}
}
6 changes: 3 additions & 3 deletions bistoury-ui/src/bin/bistoury-ui-env.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
set -euo pipefail

JAVA_HOME="/tmp/bistoury/java"
JAVA_OPTS="-Dbistoury.conf=$BISTOURY_COF_DIR -Dbistoury.cache=$BISTOURY_CACHE_DIR"
set +o nounset
test -z "$JAVA_HOME" && JAVA_HOME="/tmp/bistoury/java"
JAVA_OPTS="$JAVA_OPTS -Dbistoury.conf=$BISTOURY_COF_DIR -Dbistoury.cache=$BISTOURY_CACHE_DIR"
2 changes: 1 addition & 1 deletion script/h2/data.sql
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
insert into bistoury_user (user_code, password) values ('admin','q1mHvT20zskSnIHSF27d/A==');
insert into bistoury_user (user_code, password) values ('admin','${admin_pwd}');
insert into bistoury_app(code, name, group_code, status, creator) values ('bistoury_demo_app','测试应用','tcdev',1,'admin');
insert into bistoury_user_app (app_code, user_code) values ('bistoury_demo_app','admin');
insert into bistoury_server (server_id, ip, port, host, log_dir, room, app_code, auto_jstack_enable, auto_jmap_histo_enable) values ('bade8ba7d59b4ca0b91a044739a670aa','${local_ip}',8080,'${local_host}','${log_dir}','al','bistoury_demo_app',1,0);
14 changes: 7 additions & 7 deletions script/h2/h2.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@
H2_DIR=`pwd`
H2_LOG_FILE=$H2_DIR/h2.log
H2_PID_FILE=$H2_DIR/h2.pid
BISTOURY_TMP_DIR="/tmp/bistoury"
test -z "$BISTOURY_TMP_DIR" && BISTOURY_TMP_DIR="/tmp/bistoury"
H2_PORT_FILE="$BISTOURY_TMP_DIR/h2port.conf"

H2_DATA_BASE_URL="/tmp/bistoury/h2/bistoury;MODE=MYSQL;TRACE_LEVEL_SYSTEM_OUT=2;AUTO_SERVER=TRUE;"
H2_DATA_BASE_URL="${BISTOURY_TMP_DIR}/h2/bistoury;MODE=MYSQL;TRACE_LEVEL_SYSTEM_OUT=2;AUTO_SERVER=TRUE;"
APP_LOG_DIR="\/tmp"

LOCAL_IP=`/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"|tail -1`

H2_PORT=9092;
echo "$H2_PORT">$H2_PORT_FILE

Expand All @@ -36,18 +34,20 @@ else
fi

start(){

echo "Init tables"
$JAVA -cp h2-1.4.199.jar org.h2.tools.RunScript -url "jdbc:h2:file:$H2_DATA_BASE_URL" -script ./schema.sql

echo "Init datas"
#替换数据库初始化文件中的sql
local_host=`hostname`
APP_LOG_DIR=` echo $APP_LOG_DIR | sed 's#\/#\\\/#g'`
sed 's/${local_ip}/'$LOCAL_IP'/g' data.sql | sed 's/${local_host}/'$local_host'/g'|sed 's/${log_dir}/'$APP_LOG_DIR'/g' >newdata.sql

test -z "$LOCAL_IP" && LOCAL_IP=`/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"|tail -1`
test -z "$BISTOURY_ADMIN_PWD" && export BISTOURY_ADMIN_PWD="q1mHvT20zskSnIHSF27d/A=="
sed 's@${local_ip}@'$LOCAL_IP'@g' data.sql | sed 's@${admin_pwd}@'$BISTOURY_ADMIN_PWD'@g' | \
sed 's/${local_host}/'$local_host'/g'|sed 's@${log_dir}@'$APP_LOG_DIR'@g' >newdata.sql
$JAVA -cp h2-1.4.199.jar org.h2.tools.RunScript -url "jdbc:h2:file:$H2_DATA_BASE_URL" -script ./newdata.sql

unset BISTOURY_ADMIN_PWD
rm -rf newdata.sql

echo "Start h2 database"
Expand Down
11 changes: 9 additions & 2 deletions script/quick_start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,19 @@ BISTOURY_AGENT_APP_LIB_CLASS="";
BISTOURY_TMP_DIR="/tmp/bistoury"
BISTOURY_PROXY_CONF_FILE="$BISTOURY_TMP_DIR/proxy.conf"

LOCAL_IP=`/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"|tail -1`

start(){

test -z "$LOCAL_IP" && LOCAL_IP=`/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"|tail -1`
export JAVA_OPTS="$JAVA_OPTS -Dbistoury.ui.register_disabled=true"
test -z "$BISTOURY_ADMIN_PWD" && BISTOURY_ADMIN_PWD=admin
cd $BISTOURY_UI_BIN_DIR
echo "BISTOURY_ADMIN_PWD=$BISTOURY_ADMIN_PWD"
export BISTOURY_ADMIN_PWD=$(java -cp '../lib/*' qunar.tc.bistoury.ui.security.PasswordEncoderMain "$BISTOURY_ADMIN_PWD" | awk '/encodePwd:/{print $4}')
#echo "BISTOURY_ADMIN_PWD=$BISTOURY_ADMIN_PWD"

cd $H2_DATABASE_DIR
./h2.sh -j $2 -i $LOCAL_IP -l $APP_LOG_DIR start
unset BISTOURY_ADMIN_PWD
sleep 5

cd $BISTOURY_PROXY_BIN_DIR
Expand Down