环境前提搭建
-
创建数据库和表
后面有源码,直接导入源码里面的sql文件就可以了
具体实现
使用数据库的账号密码并且获取对应角色实际上就是重写了一部分认证接口,主要就是通过在SpringSecurity的配置文件上声明了,userDetailsService已经由一个继承了UserDetailsService的接口重写了。
- 写一个通过用户名查询到账号密码以及该用户拥有的角色的三层
实体类
package com.pning.studysecurity.pojo;
import lombok.*;
import java.util.List;
@Data
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class SystemUser {
private String username;
private String passworld;
private List<String> roles;
}
service层
继承UserDetailsService 的接口
package com.pning.studysecurity.service;
import com.pning.studysecurity.pojo.SystemUser;
import org.springframework.security.core.userdetails.UserDetailsService;
public interface ISystemUser extends UserDetailsService {
}
service实现类
package com.pning.studysecurity.service.imp;
import com.pning.studysecurity.mapper.SystemUserMapper;
import com.pning.studysecurity.pojo.SystemUser;
import com.pning.studysecurity.service.ISystemUser;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@Service
public class SystemUserImp implements ISystemUser {
@Resource
SystemUserMapper systemUserMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
SystemUser systemUser = systemUserMapper.selectSystemUserByUserName(username);//通过用户名从数据库中获取密码和拥有角色
if(systemUser!=null){
List<SimpleGrantedAuthority> roles = new ArrayList<>();
for (String roleName:systemUser.getRoles()){
roles.add(new SimpleGrantedAuthority(roleName));
}
return new User(systemUser.getUsername(),"{noop}"+systemUser.getPassworld(),roles);
}
return null;
}
}
mapper层
package com.pning.studysecurity.mapper;
import com.pning.studysecurity.pojo.SystemUser;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface SystemUserMapper {
SystemUser selectSystemUserByUserName(@Param("username") String username);
}
sql语句
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pning.studysecurity.mapper.SystemUserMapper">
<select id="selectSystemUserByUserName" resultMap="SystemUserLogin">
SELECT
u.username,
u.passworld,
r.r_name
FROM USER u
LEFT JOIN user_role ur ON u.id=ur.uid
LEFT JOIN role r ON ur.rid=r.r_id
where u.username=#{username}
</select>
<resultMap type="com.pning.studysecurity.pojo.SystemUser" id="SystemUserLogin">
<result property="username" column="username"/>
<result property="passworld" column="passworld"/>
<collection property="roles" ofType="String">
<result column="r_name"/>
</collection>
</resultMap>
</mapper>
SpringSecurity的config配置文件
package com.pning.studysecurity.config;
import com.pning.studysecurity.service.ISystemUser;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import javax.annotation.Resource;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
ISystemUser iSystemUser;
//授权
@Override
protected void configure(HttpSecurity http) throws Exception {
//根据格式要求,如果我们要实现从数据库中获取这个用户的角色并注入到这个角色中去的话需要按照规定角色的角色名写法格式:ROLE_角色名,这样SpringSecurity才能识别这个角色
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/toLogin").permitAll()
.antMatchers("/leave_1/**").hasRole("vip1")
.antMatchers("/leave_2/**").hasRole("vip2")
.antMatchers("/leave_3/**").hasRole("vip3");
http.formLogin().loginPage("/toLogin").loginProcessingUrl("/securitylogin");
http.logout().deleteCookies("remove").invalidateHttpSession(true).logoutSuccessUrl("/toLogin");//通过阅读源码我们可发现注销必须是post方法
http.rememberMe();
}
//认证
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(iSystemUser);//通过一个继承了UserDetailsService的接口来实现
}
}