且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何使用java和xml配置在Spring Security中配置jdbc身份验证管理器?

更新时间:2021-07-26 21:49:28

为需要此服务的其他人造福.

For the benefit of others who is in need of this.

要实现jdbcAuthentication,您需要向数据库表中写入两个查询
Query1: usersByUsernameQuery (设置用于根据用户名查找用户的查询.)
Query2: authoritiesByUsernameQuery (设置用于根据用户名查找用户权限的查询.)

For implementing jdbcAuthentication you need to write two queries to your database tables
Query1: usersByUsernameQuery (Sets the query to be used for finding a user by their username.)
Query2: authoritiesByUsernameQuery (Sets the query to be used for finding a user's authorities by their username.)

它可能是java配置或xml配置,您所需要做的就是
1.创建数据源
2.通过注入数据源依赖性并配置usersByUsernameQuery和AuthorityByUsernameQuery在AuthenticationManagerBuilder中配置jdbc身份验证. 3.配置HttpSecurity.下面提供了详细信息和默认值
-----为这些URL的

Either it may be java configuration or xml configuration, all you need to do is
1. Create datasource
2. Configure jdbc authentication in AuthenticationManagerBuilder by injecting datasource dependency and configuring usersByUsernameQuery and authoritiesByUsernameQuery.
3. Configure HttpSecurity. Details and defaults given below
----- Configure intercept-url pattern and authorization for those url's

Default role of unauthenticated user = ROLE_ANONYMOUS

-----配置表单登录,以避免出现默认的登录屏幕和下面给出的默认行为.

----- Configure form login to avoid default login screen and default behavior given below.

login-page        = "/login" with HTTP get
usernameParameter = "username"
passwordParameter = "password"
failureUrl        = "/login?error"
loginProcessingUrl= "/login" with HTTP post
successUrl        = "/"

-----配置注销以覆盖默认行为.

----- Configure logout to override default behavior.

logoutUrl        = "/logout"
logoutSuccessUrl = "/login?logout"

-----配置会话管理以覆盖默认行为

----- Configure session management to override default behavior

expiredUrl         = "/login?expired"
invalidate-session = true //you can set false and use delete-cookies="JSESSIONID"
maximumSessions    = The default is to allow any number of sessions for a users.

Javaconfig方式

如果这不足以从我的github存储库下载. 使用Java配置工作的Spring Security副本

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter 
{

    public DataSource dataSource()
    {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/springmvc");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        dataSource.setInitialSize(2);
        dataSource.setMaxActive(5);

        return dataSource;
    }


    @Autowired
    public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception
    {
        auth.jdbcAuthentication().dataSource(dataSource()).passwordEncoder(passwordEncoder())
                .usersByUsernameQuery("select username, password, enabled from userdetails where userName=?")
                .authoritiesByUsernameQuery(
                        "select ud.username as username, rm.name as role from userdetails ud INNER JOIN rolemaster rm ON rm.id = ud.roleId  where username = ?");
    }

    @Override
    protected void configure(final HttpSecurity http) throws Exception
    {
        http
        .authorizeRequests()
            .antMatchers("/resources/**", "/", "/login", "/api/**").permitAll()
            .antMatchers("/config/*", "/app/admin/*")
            .hasRole("ADMIN")
            .antMatchers("/app/user/*")
            .hasAnyRole("ADMIN", "USER")
        .and().exceptionHandling()
            .accessDeniedPage("/403")
        .and().formLogin()
            .loginPage("/login")
            .usernameParameter("userName").passwordParameter("password")
            .defaultSuccessUrl("/app/user/dashboard")
            .failureUrl("/login?error=true")
        .and().logout()
            .logoutSuccessHandler(new CustomLogoutSuccessHandler())
            .invalidateHttpSession(true)
        .and()
            .csrf()
                .disable();

        http.sessionManagement().maximumSessions(1).expiredUrl("/login?expired=true");
    }

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

}

XML配置方式(不适用于Spring Boot)

如果这不足以从我的github存储库下载. 使用XML配置工作的Spring安全副本

<?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.xsd  
    http://www.springframework.org/schema/security  
    http://www.springframework.org/schema/security/spring-security.xsd">  

    <http auto-config="true" use-expressions="true" create-session="ifRequired">
        <csrf disabled="true"/>

        <intercept-url pattern="/resources/**" access="permitAll" />
        <intercept-url pattern="/" access="permitAll" />
        <intercept-url pattern="/login" access="permitAll" />
        <intercept-url pattern="/api/**" access="permitAll" />

        <intercept-url pattern="/config/*" access="hasRole('ROLE_ADMIN')" />
        <intercept-url pattern="/app/admin/*" access="hasRole('ROLE_ADMIN')" />

        <intercept-url pattern="/app/user/*" access="hasAnyRole('ROLE_USER', 'ROLE_ADMIN')" />

        <access-denied-handler error-page="/403" />

        <form-login 
            login-page="/login" 
            default-target-url="/app/user/dashboard" 
            authentication-failure-url="/login?error=true" 
            username-parameter="userName"
            password-parameter="password" />

        <logout invalidate-session="false" success-handler-ref="customLogoutSuccessHandler"/>

        <session-management invalid-session-url="/login?expired=true">
            <concurrency-control max-sessions="1" />
        </session-management>

    </http>


    <authentication-manager>
      <authentication-provider>
        <password-encoder ref="encoder" /> 
        <jdbc-user-service data-source-ref="dataSource"
          users-by-username-query=
            "select username, password, enabled from userdetails where userName=?"
          authorities-by-username-query=
            "select ud.username as username, rm.name as role from userdetails ud INNER JOIN rolemaster rm ON rm.id = ud.roleId  where username = ?" />
      </authentication-provider>
    </authentication-manager>

    <beans:bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
    <beans:bean id="customLogoutSuccessHandler" class="com.pvn.mvctiles.configuration.CustomLogoutSuccessHandler" />

    <beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
         <beans:property name="driverClassName" value="com.mysql.jdbc.Driver" />
         <beans:property name="url" value="jdbc:mysql://localhost:3306/springmvc" />
         <beans:property name="username" value="root"/>
         <beans:property name="password" value="root"/>
         <beans:property name="initialSize" value="2" />
         <beans:property name="maxActive" value="5" />
    </beans:bean>       
</beans:beans>





在这里您需要覆盖loadUserByUsername方法
1.通过在方法中作为争论传递的用户名从数据库中加载用户密码.
2.从数据库中为用户加载权限,并构建GrantedAuthority
的列表 3.通过传递在步骤1和步骤2中获取的密码和授权来创建用户
4.返回UserDetail对象,以便spring容器本身负责认证和授权.

Here you need to override loadUserByUsername method
1. load user password from database by username passed as arguement in the method.
2. Load authorities for user from database and construct a list of GrantedAuthority
3. Create User by passing password and authorities fetched in step 1 and step 2
4. Return UserDetail object so that authentication and authorization will be taken care by spring container itself.

@Component
public class UserDaoImpl implements UserDao, UserDetailsService
{

    Logger          OUT = LoggerFactory.getLogger(UserDaoImpl.class);

    @Autowired
    SessionFactory  sessionFactory;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
    {
        try (Session session = sessionFactory.openSession();)
        {

            CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
            CriteriaQuery<DbUserDetails> userCriteria = criteriaBuilder.createQuery(DbUserDetails.class);
            Root<DbUserDetails> userRoot = userCriteria.from(DbUserDetails.class);
            userCriteria.select(userRoot).where(criteriaBuilder.equal(userRoot.get("userName"), username));

            Query<DbUserDetails> userQuery =session.createQuery(userCriteria);
            DbUserDetails dbUser = userQuery.getSingleResult();

            CriteriaQuery<RoleMaster> roleCriteria = criteriaBuilder.createQuery(RoleMaster.class);
            Root<RoleMaster> roleRoot = roleCriteria.from(RoleMaster.class);
            roleCriteria.select(roleRoot).where(criteriaBuilder.equal(roleRoot.get("id"), dbUser.getRoleId()));

            Query<RoleMaster> roleQuery =session.createQuery(roleCriteria);
            RoleMaster role = roleQuery.getSingleResult();

            List<GrantedAuthority> authList = new ArrayList<>();
            authList.add(new SimpleGrantedAuthority(role.getName()));

            return new User(username, dbUser.getPassword(),true, true, true, true, authList);
        }
        catch (Exception e)
        {
            OUT.error("Exception - {}", e);
            throw new UsernameNotFoundException("Exception caught", e);
        }
    }
}

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter 
{   
    @Autowired
    UserDaoImpl userDaoImpl;

    @Autowired
    public void configureUserDetailsService(AuthenticationManagerBuilder auth) throws Exception
    {
        auth.userDetailsService(userDaoImpl);
    }
    ...
}