在上一篇基本配置了一些文件中,基本可以在文件中指定用户名和密码来进行实现SpringSecurity的验证,
这次和mynatis一起来配合使用

加入mybatis的配置文件:

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 别名 -->
    <typeAliases>
        <package name="szh.security.entity"/>
    </typeAliases>
</configuration>

在spring的ApplicationContext.xml中配置数据源
ApplicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="    
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-4.0.xsd  
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
    <context:component-scan base-package="szh.security"></context:component-scan>
    <context:property-placeholder location="classpath:jdbc.properties" />
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${drivername}"></property>
        <property name="url" value="${url}"></property>
        <property name="username" value="${username}"></property>
        <property name="password" value="${password}"></property>
    </bean>
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
        <property name="mapperLocations" value="classpath:mapper/*.xml"></property>
    </bean><!-- 查找mapper -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="szh.security.dao"></property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    </bean>
    <!-- 配置事物 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
</beans>

然后建立dao层,和server层以及对应mapper(这里省略)
实现UserDetailService里面的loadUserByUsername方法

public class MyUserDetailService implements UserDetailsService  {
    @Autowired
    UserDao userdao;
    @Override
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException {
        MyUser user =userdao.getUserByName(username);
        if(user==null)
        {
            throw new  UsernameNotFoundException("找不到该用户");
        }
//这里最好的做法就是遍历用户身份,获取用户权限
//        Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
//        SimpleGrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role);
//        grantedAuthorities.add(grantedAuthority);
        return new MyUserDetail(user, getAuthorities(user.getUser_role()));
    }

    private Collection<GrantedAuthority> getAuthorities(String role) {
        Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        SimpleGrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role);
        grantedAuthorities.add(grantedAuthority);
        return grantedAuthorities;
    }

}

UserDetail

public class MyUserDetail implements UserDetails {
    private MyUser myUser;
    private Collection<? extends GrantedAuthority> authorities;

    public MyUserDetail(MyUser user,Collection<? extends GrantedAuthority> authorities) {
        this.myUser = user;
        this.authorities = authorities;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        // TODO Auto-generated method stub
        return authorities;
    }

    @Override
    public String getPassword() {
        return myUser.getUser_password();
    }

    @Override
    public String getUsername() {
        return myUser.getUser_name();
    }
//下面的方法可以以后再添加
    @Override
    public boolean isAccountNonExpired() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean isAccountNonLocked() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean isEnabled() {
        // TODO Auto-generated method stub
        return false;
    }

AuthenticationProvider类

关于类中的这个UsernamePasswordAuthenticationToken,Spring官方文档中给出的说明如下:

1. The username and password are obtained and combined into an instance of UsernamePasswordAuthenticationToken (an instance of
the Authentication interface, which we saw earlier).
2. The token is passed to an instance of AuthenticationManager for validation.
3. The AuthenticationManager returns a fully populated Authentication instance on successful authentication.
4. The security context is established by calling SecurityContextHolder.getContext().setAuthentication(… ) , passing in the returned
authentication object.

UsernamePasswordAuthenticationToken继承AbstractAuthenticationToken实现Authentication

所以当在页面中输入用户名和密码之后首先会进入到UsernamePasswordAuthenticationToken验证(Authentication),然后生成的Authentication会被交由AuthenticationManager来进行管理而AuthenticationManager管理一系列的AuthenticationProvider,而每一个Provider都会通UserDetailsService和UserDetail来返回一个以UsernamePasswordAuthenticationToken实现的带用户名和密码以及权限的Authentication

public class SecurityProvider implements AuthenticationProvider {
    @Autowired
    private MyUserDetailService userDetailsService;
    @Override
    public Authentication authenticate(Authentication authentication)
            throws AuthenticationException {
//
        UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;
        UserDetails userDetails = userDetailsService.loadUserByUsername(token.getName());
        if (userDetails == null) {
            throw new UsernameNotFoundException("找不到该用户");
        }
        if(!userDetails.getPassword().equals(token.getCredentials().toString()))
        {
              throw new BadCredentialsException("密码错误");
        }
        return new UsernamePasswordAuthenticationToken(userDetails,userDetails.getPassword(),userDetails.getAuthorities());
    }

    @Override
    public boolean supports(Class<?> authentication) {
        // TODO Auto-generated method stub
        return UsernamePasswordAuthenticationToken.class.equals(authentication);
    }

}

项目地址:https://github.com/Somersames...


Somersames
79 声望4 粉丝