GVKun编程网logo

使用带有默认身份验证提供程序的Spring-Security PasswordEncoder?

15

本文将介绍使用带有默认身份验证提供程序的Spring-SecurityPasswordEncoder?的详细情况,。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些

本文将介绍使用带有默认身份验证提供程序的Spring-Security PasswordEncoder?的详细情况,。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于005-SpringBoot2.x整合Security5(解决 There is no PasswordEncoder mapped for the id "null")、@Autowire在Spring Security自定义身份验证提供程序中不起作用、Java Spring Security – User.withDefaultPasswordEncoder()已弃用?、Java Spring Security配置-多个身份验证提供程序的知识。

本文目录一览:

使用带有默认身份验证提供程序的Spring-Security PasswordEncoder?

使用带有默认身份验证提供程序的Spring-Security PasswordEncoder?

我正在使用Spring 4.0.8 RELEASE和Spring-Security 3.2.5 RELEASE

我正在使用HTTP Digest构建REST WebService,只有注册用户可以访问。

我的web.xml是这样的:

<servlet>
    <servlet-name>rest</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
     <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </init-param> 
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>rest</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>


<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

applicationContext.xml包含我的Controller / DAO,对此很重要,仅此而已:

<import resource="security-context.xml" />

<bean id="daoPersonal">
    <property name="dataSource" ref="dataSource" />
</bean>

现在,security-context.xml如下所示:

 <?xml version="1.0" encoding="UTF-8"?>
 <beans:beans xmlns="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-4.0.xsd
         http://www.springframework.org/schema/security
         http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <debug />
    <http entry-point-ref="digestEntryPoint">
        <headers />
        <intercept-url pattern="/**" access="ROLE_USER" />
        <custom-filter ref="digestFilter" after="BASIC_AUTH_FILTER" />
    </http>

    <beans:bean id="digestFilter">
        <beans:property name="userDetailsService" ref="daoPersonal" />
        <beans:property name="authenticationEntryPoint" ref="digestEntryPoint" />
    </beans:bean>

    <beans:bean id="digestEntryPoint">
        <beans:property name="realmName" value="Contacts Realm via Digest Authentication" />
        <beans:property name="key" value="acegi" />
    </beans:bean>

    <beans:bean id="bcryptEncoder"/>

    <authentication-manager>
        <authentication-provider user-service-ref="daoPersonal">
             <password-encoder ref="bcryptEncoder" />
        </authentication-provider>
    </authentication-manager>
 </beans:beans>

和我的PersonalDAO

 public class PersonalDAO extends NamedParameterJdbcDaoSupport implements UserDetailsService  {

 /*my other code
  ...
 */

 @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println(new Date() + " PersonalDAO loadUserByUsername: " + username);
         List<UserDetails> users = getJdbcTemplate().query(USER_QUERY,new String[] {username},new RowMapper<UserDetails>() {
                public UserDetails mapRow(ResultSet rs,int rowNum) throws SQLException {
                    String username = rs.getString(1);
                    String password = rs.getString(2);
                    boolean enabled = true;
                    Collection<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
                    auths.add(new SimpleGrantedAuthority("ROLE_USER"));
                    return new User(username,password,enabled,true,auths);
                }
            });
         if(users.size()==0){
             throw new UsernameNotFoundException("");
         }
         System.out.println(new Date() + "Users Found: " + users.size());
         return users.get(0);
    }
 }

在身份验证提供程序内部没有密码编码器的情况下,它可以使用数据库中的纯文本密码按预期工作。但是使用密码编码器(并且数据库中的密码已更改为bcrypt编码的密码),浏览器会指出登录错误并再次提示。从我的输出中,我可以看到我的PersonalDAO已被调用并找到了用户。

我的数据库中仍然有另一个用户,该用户仍然具有纯文本密码,我尝试使用该用户登录,同时仍使bcryptencoder处于活动状态,我在服务器日志中得到了该密码:

 org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder matches
 WARNING: Encoded password does not look like BCrypt

现在,我至少可以看到调用了BCryptEncoder,但是它得到了匹配,这意味着没有进行编码,而且我仍然无法进入。(这可能是预期的)。

我想念什么?

编辑:

日志输出不多,但是这里:

Fri Dec 05 15:07:06 CET 2014 PersonalDAO loadUserByUsername: test
Fri Dec 05 15:07:06 CET 2014 Users Found: 1

db中的加密密码:$ 2a $ 10 $ HWX95PBi7pob2bmIHXka3ecMcfsSvEifV3Z6J0CAb3vpWs8N9j5xS

005-SpringBoot2.x整合Security5(解决 There is no PasswordEncoder mapped for the id

005-SpringBoot2.x整合Security5(解决 There is no PasswordEncoder mapped for the id "null")

问题描述

  SpringBoot升级到了2.0之后的版本,Security也由原来的版本4升级到了5

使用WebSecurityConfigurerAdapter继承重置方法

protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //inMemoryAuthentication 从内存中获取  
        auth.inMemoryAuthentication().withUser("user1").password("123456").roles("USER"); 
}

此时

  java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

在Spring Security中密码的存储格式是“{id}…………”。前面的id是加密方式,id可以是bcrypt、sha256等,后面跟着的是加密后的密码。也就是说,程序拿到传过来的密码的时候,会首先查找被“{”和“}”包括起来的id,来确定后面的密码是被怎么样加密的,如果找不到就认为id是null。这也就是为什么我们的程序会报错:There is no PasswordEncoder mapped for the id “null”。官方文档举的例子中是各种加密方式针对同一密码加密后的存储形式,原始密码都是“password”。

{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG 
{noop}password 
{pbkdf2}5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc 
{scrypt}$e0801$8bWJaSu2IKSn9Z9kM+TPXfOc/9bdYSrN1oD9qfVThWEwdRTnO7re7Ei+fUZRJ68k9lTyuTeUp4of4g24hHnazw==$OAOec05+bXxvuu/1qZ6NUR+xQYvYv7BeL1QxwRpY5Pc=  
{sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0

方式一、增加具体实例

内存

protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //inMemoryAuthentication 从内存中获取  
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("user1").password(new BCryptPasswordEncoder().encode("123456")).roles("USER");
}

在inMemoryAuthentication()后面多了".passwordEncoder(new BCryptPasswordEncoder())",相当于登陆时用BCrypt加密方式对用户密码进行处理。以前的".password("123456")" 变成了 ".password(new BCryptPasswordEncoder().encode("123456"))" ,这相当于对内存中的密码进行Bcrypt编码加密。比对时一致,说明密码正确,允许登陆。

数据库

如果是注入userDetailsService

//注入userDetailsService的实现类
auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder());

如果你用的是在数据库中存储用户名和密码,那么一般是要在用户注册时就使用BCrypt编码将用户密码加密处理后存储在数据库中。并且修改configure()方法,加入".passwordEncoder(new BCryptPasswordEncoder())",保证用户登录时使用bcrypt对密码进行处理再与数据库中的密码比对。

没有加密方式的

protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().passwordEncoder(NoOpPasswordEncoder.getInstance())
                .withUser("admin").password("123456").roles("USER", "ADMIN");
    }

如果配置了spring security oauth2

public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory().withClient("client").secret("{noop}secret")
                .authorizedGrantTypes("client_credentials", "password", "refresh_token").scopes("all");
    }

 

@Autowire在Spring Security自定义身份验证提供程序中不起作用

@Autowire在Spring Security自定义身份验证提供程序中不起作用

我们有Spring MVC应用程序。我们正在尝试将Spring安全性集成到其中。

我们已经编写了自定义身份验证提供程序,它将执行身份验证工作。

以下是我的自定义身份验证提供程序的代码。

    public class CustomAuthenticationProvider extends DaoAuthenticationProvider {    @Autowired    private AuthenticationService authenticationService;    @Override    public Authentication authenticate(Authentication authentication) {        CustomAuthenticationToken auth = (CustomAuthenticationToken) authentication;        String username = String.valueOf(auth.getPrincipal());        String password = String.valueOf(auth.getCredentials());        try {            Users user = new User();            user.setUsername(username);            user.setPassword(PasswordUtil.encrypt(password));            user = authenticationService.validateLogin(user);            return auth;        } catch (Exception e) {            throw new BadCredentialsException("Username/Password does not match for " + username);        }    }    @Override    public boolean supports(Class<? extends Object> authentication) {        return (CustomAuthenticationToken.class.isAssignableFrom(authentication));    }}

在这里,我在下一行获取NullpointerException

user = authenticationService.validateLogin(user);

不会在自定义身份验证提供程序中自动连接authenticationService。虽然相同的服务authenticationService在我的MVC控制器中以相同的方式自动接线。

这是因为身份验证提供程序是Spring安全组件吗?

下面是我的web.xml

    <context-param>    <param-name>contextConfigLocation</param-name>    <param-value>        /WEB-INF/spring/myApp-security.xml    </param-value></context-param><servlet>    <servlet-name>myApp</servlet-name>    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>    <init-param>        <param-name>contextConfigLocation</param-name>        <param-value>/WEB-INF/spring/myApp-servlet.xml</param-value>    </init-param>    <load-on-startup>1</load-on-startup></servlet><servlet-mapping>    <servlet-name>myApp</servlet-name>    <url-pattern>/</url-pattern></servlet-mapping><filter>    <filter-name>springSecurityFilterChain</filter-name>    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class></filter><filter-mapping>    <filter-name>springSecurityFilterChain</filter-name>    <url-pattern>/*</url-pattern></filter-mapping><listener>    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>

编辑1:-

我在我的spring安全配置文件中添加了以下几行。

<beans:bean id="customAuthenticationProvider">    <beans:property name="userDetailsService" ref="userDetailsService"/>   </beans:bean>

请帮助如何在Spring安全组件中自动连接服务类?

答案1

小编典典

也许未在根应用程序上下文中启用自动装配后处理器(但在DispatcherServlet的上下文中由于<mvc:annotation-driven>或的影响而启用了<context:component-scan>)。

您可以通过添加<context:annotation-config>到中启用它myApp-security.xml

Java Spring Security – User.withDefaultPasswordEncoder()已弃用?

Java Spring Security – User.withDefaultPasswordEncoder()已弃用?

我是java spring security的新手,并且遵循Spring.io tutorial guide.
作为其中的一部分,我根据需要编辑了WebSecurityConfig类:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
      http
        .authorizeRequests()
            .antMatchers("/","/home").permitAll()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/login")
            .permitAll()
            .and()
        .logout()
            .permitAll();
    }

    @Bean
    @Override
    public UserDetailsService userDetailsService() {
        UserDetails user =
         User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build();

    return new InMemoryUserDetailsManager(user);
    }
}

在userDetailService()方法中,它使用withDefaultPasswordEncoder(),现在已弃用,如文档中所示:withDefaultPasswordEncoder()

不幸的是,我没有找到替代方案,在不使用弃用方法的情况下完成本教程.
如果可能,有人能为此提供替代方案吗?

谢谢!

注意:我附上了几个错误的屏幕截图,以及我的gradle文件

image 1: The error I am receiving

image 2: My gradle file

最佳答案
编辑:删除旧答案,误解了这个问题.这是新的:

User.withDefaultPasswordEncoder()仍然可以用于演示,你不必担心这是你正在做什么 – 即使它已被弃用 – 但在生产中,你的源代码中不应该有纯文本密码.

您应该做什么而不是使用当前的userDetailsS​​ervice()方法是following:

private static final String ENCODED_PASSWORD = "$2a$10$AIUufK8g6EFhBcumRRV2L.AQNz3Bjp7oDQVFiO5JJMBFZQ6x2/R/2";


@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
        .passwordEncoder(passwordEncoder())
        .withUser("user").password(ENCODED_PASSWORD).roles("USER");
}


@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

其中ENCODED_PASSWORD是用BCrypt编码的secret123.你也可以像下面这样编程编码:passwordEncoder().encode(“secret123”).

这样,即使您将代码推送到公共存储库,人们也不会知道密码,因为ENCODED_PASSWORD只显示密码的编码版本而不是纯文本版本,但是因为您知道$2a $10 $AIUufK8g6EFhBcumRRV2L.AQNz3Bjp7oDQVFiO5JJMBFZQ6x2 / R / 2实际上是字符串secret123的编码密码,而其他人没有,您的内存用户凭证用户:secret123将不会受到损害.

请注意,为了示例,我将其保留在静态变量中.

Java Spring Security配置-多个身份验证提供程序

Java Spring Security配置-多个身份验证提供程序

如何解决Java Spring Security配置-多个身份验证提供程序?

也许这会帮助你:

@Configuration
@EnableWebSecurity
@Profile("container")
public class XSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private AuthenticationProvider authenticationProvider;

@Autowired
private AuthenticationProvider authenticationProviderDB;

@Override
@Order(1)

protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(authenticationProvider);
}

@Order(2)
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(authenticationProviderDB);
}

@Override
  public void configure(WebSecurity web) throws Exception {
    web
      .ignoring()
         .antMatchers("/scripts/**","/styles/**","/images/**","/error/**");
  }

@Override
public void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/rest/**").authenticated()
            .antMatchers("/**").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .successHandler(new AuthenticationSuccessHandler() {
                @Override
                public void onAuthenticationSuccess(
                        HttpServletRequest request,
                        HttpServletResponse response,
                        Authentication a) throws IOException, servletexception {
                            //To change body of generated methods,
                            response.setStatus(HttpServletResponse.SC_OK);
                        }
            })
            .failureHandler(new AuthenticationFailureHandler() {

                @Override
                public void onAuthenticationFailure(
                        HttpServletRequest request,
                        HttpServletResponse response,
                        AuthenticationException ae) throws IOException, servletexception {
                            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                        }
            })
            .loginProcessingUrl("/access/login")
            .and()
            .logout()
            .logoutUrl("/access/logout")                
            .logoutSuccessHandler(new logoutSuccessHandler() {
                @Override
                public void onlogoutSuccess(
                        HttpServletRequest request, 
                        HttpServletResponse response, 
                        Authentication a) throws IOException, servletexception {
                    response.setStatus(HttpServletResponse.SC_NO_CONTENT);
                }
            })
            .invalidateHttpSession(true)
            .and()
            .exceptionHandling()
            .authenticationEntryPoint(new Http403ForbiddenEntryPoint())
            .and()
            .csrf()//disabled CSRF protection
            .disable();
    }
} 

在Spring Boot中,这对我有用:

每个身份验证提供程序都按顺序进行测试。如果通过,则跳过其后面的身份验证提供程序

auth.userDetailsService(userDetailsService)...

然后:

auth.ldapAuthentication()....
@EnableRedisHttpSession
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private CustomUserDetailsService userDetailsService;

@Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {

    //each Authentication provider is tested in order
    //if one passes then its following Authentication providers are skipped

    //DataBase Authentication
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordencoder());



    LdapContextSource ldapContextSource = new LdapContextSource();


    ldapContextSource.setUrl("ldap://192.168.XXX.XXX:389");
    ldapContextSource.setBase("dc=companyname,dc=com");
    ldapContextSource.setUserDn("cn=user,cn=testgroup,ou=Test,dc=companyname,dc=com");
    ldapContextSource.setPassword("user1234");
    ldapContextSource.afterPropertiesSet();



    //LDAP Authentication
    auth.ldapAuthentication()
        //The {0} in the (uid={0}) will be replaced by the username entered in the form.
        .userSearchBase("ou=Group")
        .userSearchFilter("uid={0}")

        //.userDnPatterns("uid={0},ou=people")//does the same thing 

        //Specifies where the search for Roles start
        //.groupSearchBase("ou=mathematicians")
        //in groups we search for member
        //.groupSearchFilter("member={0}")
        //.contextSource().ldif("classpath:test-server.ldif");

    .contextSource(ldapContextSource);



}

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()


            .antMatchers("/hello").access("hasRole(''ROLE_ADMIN'')")
            .antMatchers("/index").fullyAuthenticated()
            .antMatchers("/").fullyAuthenticated()
            .antMatchers("/home").fullyAuthenticated()
            .anyRequest().permitAll()

            .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .usernameParameter("username").passwordParameter("password")
            .and()
            .logout()
                .logoutSuccessUrl("/login?logout")
                .permitAll()
            .and()
                .exceptionHandling()
                .accessDeniedPage("/403")
            .and()
                .csrf()
                .disable();



}

@Bean(name = "passwordEncoder")
public PasswordEncoder passwordencoder() {
    return new BCryptPasswordEncoder();
}
}

解决方法

在Spring Security中,有多个身份验证提供程序的参考,但是找不到Java config中的示例。

以下链接给出了XML表示法: Spring Security中的多个身份验证提供程序

我们需要使用LDAP或DB进行身份验证

下面是我们的示例代码:

@Configuration
@EnableWebSecurity
public class XSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private AuthenticationProvider authenticationProvider;

    @Autowired
    private AuthenticationProvider authenticationProviderDB;


    @Override
    @Order(1)

    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authenticationProvider);
    }


    @Order(2)
    protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authenticationProviderDB);
    }

    @Override
      public void configure(WebSecurity web) throws Exception {
        web
          .ignoring()
             .antMatchers("/scripts/**","/styles/**","/images/**","/error/**");
      }
    ______

    @Override
    @Order(1)
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
        .authorizeRequests()
            .antMatchers("/","/logout","/time").permitAll()
                    .antMatchers("/admin").hasRole("ADMIN")         
                        .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/index")
            .loginProcessingUrl("/perform_login")
            .usernameParameter("email")
            .passwordParameter("password")
            .failureUrl("/index?failed=true")
            .defaultSuccessUrl("/summary",true)
            .permitAll()
            .and()
         .logout().logoutUrl("/logout")
                  .logoutSuccessUrl("/index?logout=true").permitAll()
            .and()
            .exceptionHandling().accessDeniedPage("/error403")
        .and().authenticationProvider(authenticationProvider);

    }

    @Order(1)
    protected void configureDB(HttpSecurity http) throws Exception {
        http.csrf().disable()
        .authorizeRequests()
            .antMatchers("/","/logout").permitAll()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/index")
            .loginProcessingUrl("/perform_login")
            .usernameParameter("email")
            .passwordParameter("password")
            .failureUrl("/index?failed=true")
            .defaultSuccessUrl("/summary",true)
            .permitAll()
            .authenticationProvider(authenticationProviderDB)
    //This line giving compilation error stating authenticationProvider is not available in formloginconfigurer

         .and()
         .logout().logoutUrl("/logout")
                  .logoutSuccessUrl("/index?logout=true").permitAll()
            .and()
            .exceptionHandling().accessDeniedPage("/error403");
    }

}

今天关于使用带有默认身份验证提供程序的Spring-Security PasswordEncoder?的介绍到此结束,谢谢您的阅读,有关005-SpringBoot2.x整合Security5(解决 There is no PasswordEncoder mapped for the id "null")、@Autowire在Spring Security自定义身份验证提供程序中不起作用、Java Spring Security – User.withDefaultPasswordEncoder()已弃用?、Java Spring Security配置-多个身份验证提供程序等更多相关知识的信息可以在本站进行查询。

本文标签: