之前介绍了security最快捷的一种登录方式,配置文件验证。将要登陆的用户、角色信息写在配置文件中,进行登录验证。但是在实际项目中,基本不会这么去使用,对于用户的认证信息是要从数据库中进行查找和验证。

这次要记录的就是通过自定义的用户查询逻辑,对用户进行认证

XML配置

首先要将之前的security:authentication-manager配置进行修改

<security:authentication-manager id="demo">
    <security:authentication-provider user-service-ref="userService">
        <!-- 加密方式 -->
        <security:password-encoder ref="passwordEncoder"></security:password-encoder>
    </security:authentication-provider>
</security:authentication-manager>
<!-- 自定义的用户呀验证类 -->
<bean id="userService" class="com.bc.common.security.authc.CustomerUserDetailService"></bean>
<!-- 自定义密码验证类(security提供了md5的加密,这里是为了运用一下自定义密码验证类的配置) -->
<bean id="passwordEncoder" class="com.bc.common.security.password.MD5PasswordEncoder"></bean>

同时还需要对之前的http配置中增加登录的页面、请求url等。对于登录页面的编写,就不在说明了,就是正常的页面渲染而已

<security:http auto-config="true" authentication-manager-ref="demo">
    <security:headers>
        <!-- iframe保护 -->
        <security:frame-options policy="SAMEORIGIN"></security:frame-options>
    </security:headers>
    <!-- 配置需要登录的url -->
    <security:intercept-url pattern="/demo/**" access="hasAnyAuthority('ADMIN')" />
    <!-- 配置自定义登录 -->
    <!--
        login-page 登录页url
        login-processing-url 提交登录的访问url。
        default-target-url 登录后访问页面
    -->
    <security:form-login
            login-page="/backend/enter/login/index"
            login-processing-url="/backend/enter/login/ajaxurl"
            default-target-url="/demo/data/index"/>
    <!-- csrf配置 -->
    <security:csrf disabled="true"></security:csrf>
</security:http>

编写验证类

对于用户验证类,我们要实现security中的UserDetailsService接口中的loadUserByUsername函数。来获取用户的信息

public class CustomerUserDetailService implements UserDetailsService {

    @Autowired
    private AdminMapper adminMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //自定义用户查询逻辑。通过用户名查询
        QueryWrapper<AdminEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username",username)
                .eq("status",1);
        AdminEntity adminEntity = adminMapper.selectOne(queryWrapper);
        if(adminEntity == null){
            throw new UsernameNotFoundException("用户名或密码错误!");
        }
        //存在请求用户名下的用户信息,赋予默认的权限。创建User对象时权限不能为空
        List<GrantedAuthority> a = AuthorityUtils.commaSeparatedStringToAuthorityList("ADMIN");

        //这里将用户名,密码,权限传入User中。security会自动把请求密码加密和用户中的密码进行比对
        User user = new User(username,adminEntity.getPassword(),a);
        return user;
    }
}

密码验证类,实现PasswordEncoder接口中的encode(加密)、matches(比对)函数

public class MD5PasswordEncoder implements PasswordEncoder {

    @Override
    public String encode(CharSequence charSequence) {
        return Md5.encryp((String)charSequence);
    }

    @Override
    public boolean matches(CharSequence charSequence, String s) {
        return Md5.verify((String)charSequence,s);
    }
}

上述工作做完之后,再次访问我们的/demo/data/index路径,发现自动跳转到我们自定义的登录页面中

输入数据库中的用户名和密码,成功进入到页面中

springmvc + spring security的登录整合就完成了,对比之前我们自己写的登录验证、跳转的逻辑,省去了大把的时间。降低了工作量和难度