当前位置: 首页 > 知识库问答 >
问题:

Spring Security-随机盐+哈希+自定义UserDetailsService

阴高刚
2023-03-14
Security-applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
  xmlns:sec="http://www.springframework.org/schema/security"
  xmlns:beans="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/security
           http://www.springframework.org/schema/security/spring-security-3.0.xsd">

    <sec:http auto-config='true' access-denied-page="/access-denied.html">
        <!-- NO RESTRICTIONS -->        
        <sec:intercept-url pattern="/login.html" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <sec:intercept-url pattern="/*.html" access="IS_AUTHENTICATED_ANONYMOUSLY"  /> 
        <!-- RESTRICTED PAGES -->
        <sec:intercept-url pattern="/admin/*.html" access="ROLE_ADMIN" />
        <sec:intercept-url pattern="/athlete/*.html" access="ROLE_ADMIN, ROLE_STAFF" />

        <sec:form-login login-page="/login.html"
                    login-processing-url="/loginProcess"
                    authentication-failure-url="/login.html?login_error=1"
                    default-target-url="/member" />
        <sec:logout logout-success-url="/login.html"/>
    </sec:http>

    <beans:bean id="customUserDetailsService" class="PATH.TO.CustomUserDetailsService"/>
    <beans:bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder">
        <beans:constructor-arg value="512"/>
    </beans:bean>

    <sec:authentication-manager>
        <sec:authentication-provider user-service-ref="customUserDetailsService">
            <sec:password-encoder ref="passwordEncoder"> 
                <sec:salt-source user-property="salt"/> 
            </sec:password-encoder>
        </sec:authentication-provider>
    </sec:authentication-manager>
</beans:beans>
public class CustomUserDetails implements UserDetails {

    private int userID;
    private String username;
    private String password;
    private Collection<GrantedAuthority> authorities;
    private boolean accountNonExpired;
    private boolean accountNonLocked;
    private boolean credentialsNonExpired;
    private boolean enabled;
    private String salt;

    public CustomUserDetails() {
    }

    public CustomUserDetails(int userID, Collection<GrantedAuthority> authorities, String username, String password, boolean accountNonExpired, boolean accountNonLocked, boolean credentialsNonExpired, boolean enabled, String salt) {
        this.userID = userID;
        this.authorities = authorities;
        this.username = username;
        this.password = password;
        this.accountNonExpired = accountNonExpired;
        this.accountNonLocked = accountNonLocked;
        this.credentialsNonExpired = credentialsNonExpired;
        this.enabled = enabled;
        this.salt = salt;
    }

    @Override
    public Collection<GrantedAuthority> getAuthorities() {
        return authorities;
    }

    public int getUserID() {
        return userID;
    }

    public void setUserID(int userID) {
        this.userID = userID;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return accountNonExpired;
    }

    @Override
    public boolean isAccountNonLocked() {
        return accountNonLocked;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return credentialsNonExpired;
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }

    public String getSalt() {
        return salt;
    }

    public void setAccountNonExpired(boolean accountNonExpired) {
        this.accountNonExpired = accountNonExpired;
    }

    public void setAccountNonLocked(boolean accountNonLocked) {
        this.accountNonLocked = accountNonLocked;
    }

    public void setAuthorities(Collection<GrantedAuthority> authorities) {
        this.authorities = authorities;
    }

    public void setCredentialsNonExpired(boolean credentialsNonExpired) {
        this.credentialsNonExpired = credentialsNonExpired;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setSalt(String salt) {
        this.salt = salt;
    }
}
public class CustomUserDetailsService implements UserDetailsService {

    private User_dao userDao;

    @Autowired
    public void setUserDao(User_dao userDao) {
        this.userDao = userDao;
    }

    @Override
    public CustomUserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
        MyUser myUser = new MyUser();
        myUser.setUsername(username);
        try {
            userDao.getUserByUsername(myUser);
        } catch (Throwable e) {
        }
        if (myUser == null) {
            throw new UsernameNotFoundException("Username not found", username);
        } else {
            List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
            authList.add(new GrantedAuthorityImpl(myUser.getUserRole().getAuthority()));

            int userID = myUser.getUserID();
            boolean accountNonExpired = true;
            boolean accountNonLocked = myUser.isNonLocked();
            boolean credentialsNonExpired = true;
            boolean enabled = myUser.isEnabled();
            String password = "";
            String salt = "";

            password = new String(myUser.getHash);
            salt = new String(myUser.getSalt());
            CustomUserDetails user = new CustomUserDetails(userID, authList, username, password, accountNonExpired, accountNonLocked, credentialsNonExpired, enabled, salt);
            return user;
        }
    }
}
public byte[] generateSalt() throws NoSuchAlgorithmException {
    SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
    byte[] salt = new byte[20];
    random.nextBytes(salt);
    return salt;
}

public byte[] generateHash(byte[] salt, String pass) throws NoSuchAlgorithmException {
    MessageDigest digest = MessageDigest.getInstance("SHA-512");
    digest.update(salt);
    byte[] hash = digest.digest(pass.getBytes());
    return hash;
}
byte[] salt = generateSalt();
byte[] hash = generateHash(salt, password);
Which I then store in the db.

共有1个答案

封瑞
2023-03-14

我也有同样的问题,但一直没有回答,所以希望这可以在将来节省一些时间:

Spring-Security默认情况下会在比较摘要之前添加大括号。我错过了,旋转了几个小时(哦)。

确保存储(或生成)用花括号括起来的salt值(例如,当Spring说“{salt}”时,它们的真正含义是“打开花括号+您的salt值+关闭花括号”。

 类似资料:
  • 问题内容: 我正在建立一个网站,并试图决定如何加密用户密码以将其存储在SQL数据库中。 我意识到使用简单的md5(password)是非常不安全的。我正在考虑使用sha512(password.salt),并且我一直在研究生成有用盐的最佳方法。我阅读了许多文章,指出盐应尽可能地随机以增加哈希值的熵,这似乎是个好主意。但: 您需要将随机盐与哈希一起存储 鉴于攻击者以某种方式可以访问您的哈希密码(并试

  • 我记得读过一个方案,其中检查密码的过程是这样的: 给定数据库中的(哈希、盐)值, 用salt哈希密码以检查哈希, 使用旧哈希作为salt的哈希密码, 在数据库中存储(新哈希,也称为旧哈希) 我找不到原始来源无论如何,我不明白 > < li> 使用旧哈希作为salt的优势是什么(与使用随机salt相反), 这种方案的优点是什么(进一步使彩虹表攻击复杂化?),以及 如果有优势,如何使用PHPass应用

  • 问题内容: 我正在尝试在Java中生成盐,以与用于安全密码存储的哈希算法配合使用。我正在使用以下代码创建随机盐: 这应该生成一个完全安全的,随机生成的盐,以用于我的哈希算法。但是,当我运行代码时,每次都会输出相同的盐…表示生成的盐根本不是随机的。 出于明显的安全性目的,每个用户都需要一个唯一的符号,但是如果我每次创建一个新帐户时都使用此代码,则每个用户都将具有相同的符号,这一开始就破坏了它的用途。

  • 在Ubuntu 12.04上,我创建了几个用户和密码,然后立即用开膛手约翰破解这些密码。一个密码很强,但其他密码都在我的单词列表中。 约翰还在跑,但我已经在大约20分钟内破解了两个。 我读到的每一篇文章都在谈论盐是否为人所知。以此哈希为例: 盐是: 正当我是说,这不是一直都知道吗?所以盐除了防止使用彩虹桌外,真的没有任何作用,对吗? 此外,还有以下帖子: 要用多长时间的时间来暴力处理一个腌制的SH

  • 我正在为Web应用程序制作登录系统。要将密码存储在数据库中,我正在使用sha256加密密码,如下所示: 在数据库中,我存储了用户、用户密码和用于散列和验证用户登录的salt。现在,我正在向用户发送包含您的密码的电子邮件,但是当用户收到电子邮件时,由于存储在sha256加密密码中,用户收到的是一个长字符串,而不是用户应该知道的密码。 我的问题是,我可以通过任何方法向您发送实际的用户密码和非密码加密,

  • 问题内容: 这是我的情况: 一个Web应用程序对许多应用程序执行某种SSO 登录的用户,而不是单击链接,该应用就会向正确的应用发布包含用户信息(名称,pwd [无用],角色)的帖子 我正在其中一个应用程序上实现SpringSecurity以从其功能中受益(会话中的权限,其类提供的方法等) 因此,我需要开发一个 自定义过滤器 -我猜想-能够从请求中检索用户信息,通过自定义 DetailsUserSe