上篇实例中的用户都是使用的默认用户,在实际项目中用户都是通过自建表实现的,在这一篇中我们通过UserDetailService实现spring security查询数据库获取用户。

1.在数据库建用户表ids_member,并插入一条数据

CREATE TABLE `ids_member` (
  `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'id',
  `memberName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '用户名(登陆)',
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '密码',
  `realname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '真实姓名',
  `nickname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '昵称',
  `gender` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '性别',
  `age` varchar(3) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '年龄',
  `tel` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '电话',
  `officeAddress` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '办公地址',
  `address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '通讯地址',
  `createdAt` datetime DEFAULT NULL COMMENT '创建时间',
  `modifiedAt` datetime DEFAULT NULL COMMENT '最后更新时间',
  `createdBy` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '创建人',
  `modifiedBy` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '最后修改人',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

2.新建IMemberAuthMapper.java内容如下

@Repository
public interface IMemberAuthMapper {
    /**
     * 根据用户名查找用户
     *
     * @param memberName
     * @return
     */
    Member findByMemberName(String memberName);
}

3.新建IMemberAuthMapper.xml内容如下

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mfc.springsecuritydemo.dao.mapper.IMemberAuthMapper">
    <resultMap id="memberMap" type="com.mfc.springsecuritydemo.domain.Member">
        <id property="id" column="id"/>
        <result property="memberName" column="memberName"/>
        <result property="username" column="username"/>
        <result property="realname" column="realname"/>
        <result property="gender" column="gender"/>
        <result property="age" column="age"/>
        <result property="tel" column="tel"/>
        <result property="officeAddress" column="officeAddress"/>
        <result property="address" column="address"/>
        <result property="password" column="password"/>
        <result property="createdAt" column="createdAt"/>
        <result property="modifiedAt" column="modifiedAt"/>
        <result property="createdBy" column="createdBy"/>
        <result property="modifiedBy" column="modifiedBy"/>
    </resultMap>

    <!-- 根据用户名查询用户 -->
    <select id="findByMemberName" parameterType="String" resultMap="memberMap">
        SELECT a.id,
               a.memberName,
               username,
               a.realname,
               a.gender,
               a.age,
               a.tel,
               a.officeAddress,
               a.address,
               a.`password`,
               a.`createdAt`,
               a.`modifiedAt`,
               a.`createdBy`,
               a.`modifiedBy`
        FROM ids_member a
        WHERE a.memberName = #{memberName};
    </select>
</mapper>

4. 自定义UserDetailService重写loadUserByUsername(String memberName) 方法,改用查询自定义的dao,然后构造User对象

@Service("userDetailService")
public class UserDetailService implements UserDetailsService {
    @Autowired
    private IMemberAuthMapper memberAuthMapper;

    @Override
    public UserDetails loadUserByUsername(String memberName) throws UsernameNotFoundException {
        Member member = memberAuthMapper.findByMemberName(memberName);
        if (null == member) {
            throw new UsernameNotFoundException(memberName);
        }
        return new User(member.getMemberName(), member.getPassword(),
                true, true, true, true, new HashSet<>());
    }

}

5. 在SecurityConfig 重写configure(AuthenticationManagerBuilder auth)方法,通过AuthenticationManagerBuilder重新设置userDetailsService,为了方便测试使用passwordEncoder设置密码未加密方式(NoOpPasswordEncoder)

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailService userDetailService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login", "/login/authorize")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/login/authorize");
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailService)// 指定获取用户信息的userDetailsService
                .passwordEncoder(passwordEncoder());
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
}

输入用户名密码点击登陆,登陆成功

image.png