在上一篇基本配置了一些文件中,基本可以在文件中指定用户名和密码来进行实现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);
}
}