SpringSecurity入门Demo
maven包
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
配置文件
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/数据库表名
spring.datasource.username=root
spring.datasource.password=root
#扫描resources/mapper文件下的所有xml
mybatis.mapper-locations=classpath:/mapper/*.xml
1.启动类的注解
@SpringBootApplication
@MapperScan("com.abc.mapper")
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class Demo03Application {
public static void main(String[] args) {
SpringApplication.run(Demo03Application.class, args);
}
}
2.数据库表对应的对象
数据库表导入
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for sys_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`rolename` varchar(255) DEFAULT NULL,
`rolememo` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES ('1', 'USER', '普通用户');
INSERT INTO `sys_role` VALUES ('2', 'ADMIN', '管理员');
INSERT INTO `sys_role` VALUES ('3', 'READ', '只读');
-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`id` int(32) NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`realname` varchar(255) DEFAULT NULL,
`isenable` int(255) DEFAULT NULL,
`islock` int(255) DEFAULT NULL,
`iscredentials` int(255) DEFAULT NULL,
`createtime` date DEFAULT NULL,
`logintime` date DEFAULT NULL,
`isexpire` int(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES ('1', 'zs', '$2a$10$zd80NnclygXUiBsJzgneEu1tpYtnW1yomdP4lddG9ZfE5xtRDNtju', '张三', '1', '1', '1', '2021-05-16', '2021-05-16', '1');
INSERT INTO `sys_user` VALUES ('2', 'lisi', '$2a$10$zd80NnclygXUiBsJzgneEu1tpYtnW1yomdP4lddG9ZfE5xtRDNtju', '李四', '1', '1', '1', '2021-05-16', '2021-05-16', '1');
INSERT INTO `sys_user` VALUES ('3', 'admin', '$2a$10$eDNT3sUreKG/WAOsS0num.7IUkk7XKILaMLck9pfSk0dbSaQC64Ny', '管理员', '1', '1', '1', '2021-05-16', '2021-05-16', '1');
-- ----------------------------
-- Table structure for sys_user_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`userid` int(11) DEFAULT NULL,
`roleid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Records of sys_user_role
-- ----------------------------
INSERT INTO `sys_user_role` VALUES ('1', '1', '1');
INSERT INTO `sys_user_role` VALUES ('2', '2', '3');
INSERT INTO `sys_user_role` VALUES ('3', '3', '1');
INSERT INTO `sys_user_role` VALUES ('4', '3', '2');
数据库中有三张表
sys_user:用户信息表
**在这里需要注意是 用户的密码是加密的 zs密码为 456 当然也可以自己创建角色(写一个注册页面就好了) **
sys_role:用户权限表
sys_user_role:连接用户信息和权限的表
Role角色类
public class Role {
private Integer id;
private String name;
private String memo;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMemo() {
return memo;
}
public void setMemo(String memo) {
this.memo = memo;
}
@Override
public String toString() {
return "Role{" +
"id=" + id +
", name='" + name + '\'' +
", memo='" + memo + '\'' +
'}';
}
}
User角色类
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.Date;
import java.util.List;
//这里继承 UserDetails的原因是在配置文件(CustomSecurityConfig)中需要用户的用户名 ,密码 ,拥有的角色权限等...
//而在配置文件中 userDetailsService接口的实现类 的方法loadUserByUsername 返回的类型是UserDetails
//所有在这里 user是需要继承 UserDetails类型的
public class User implements UserDetails {
//用户唯一标识
private Integer id;
//用户名
private String username;
//密码
private String password;
private String realname;
//用户是否过期
private boolean isExpired;
//用户是否被锁
private boolean isLocked;
private boolean isCredentials;
//用户是否被启用
private boolean isEnabled;
//创建用户对象时间
private Date createTime;
//用户上次登录的时间
private Date loginTime;
//存放权限
private List<GrantedAuthority> authorities;
public boolean getExpired() {
return isExpired;
}
public boolean getLocked() {
return isLocked;
}
public boolean getCredentials() {
return isCredentials;
}
public User() {
}
public User(String username, String password, String realname,
boolean isExpired, boolean isLocked,
boolean isCredentials, boolean isEnabled,
Date createTime, Date loginTime,List<GrantedAuthority> authorities) {
this.username = username;
this.password = password;
this.realname = realname;
this.isExpired = isExpired;
this.isLocked = isLocked;
this.isCredentials = isCredentials;
this.isEnabled = isEnabled;
this.createTime = createTime;
this.loginTime = loginTime;
this.authorities = authorities;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return isExpired;
}
@Override
public boolean isAccountNonLocked() {
return isLocked;
}
@Override
public boolean isCredentialsNonExpired() {
return isCredentials;
}
@Override
public boolean isEnabled() {
return isEnabled;
}
public Integer getId() {
return id;
}
public Date getCreateTime() {
return createTime;
}
public Date getLoginTime() {
return loginTime;
}
public String getRealname() {
return realname;
}
public void setId(Integer id) {
this.id = id;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setRealname(String realname) {
this.realname = realname;
}
public void setExpired(boolean expired) {
isExpired = expired;
}
public void setLocked(boolean locked) {
isLocked = locked;
}
public void setCredentials(boolean credentials) {
isCredentials = credentials;
}
public void setEnabled(boolean enabled) {
isEnabled = enabled;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public void setLoginTime(Date loginTime) {
this.loginTime = loginTime;
}
public void setAuthorities(List<GrantedAuthority> authorities) {
this.authorities = authorities;
}
@Override
public String toString() {
return "SysUser{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", realname='" + realname + '\'' +
", isExpired=" + isExpired +
", isLocked=" + isLocked +
", isCredentials=" + isCredentials +
", isEnabled=" + isEnabled +
", createTime=" + createTime +
", loginTime=" + loginTime +
", authorities=" + authorities +
'}';
}
}
3.配置类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
@EnableWebSecurity
public class CustomSecurityConfig extends WebSecurityConfigurerAdapter {
@Qualifier("JDBCUserDetailsService")
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//从数据库中查询的角色是需要用 userDetailsService()方法
auth.userDetailsService(userDetailsService)
//密码加密的方式
.passwordEncoder(new BCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
//进入index 不需要登录
.antMatchers("/index").permitAll()
// 进入/access/user/** 需要USER
.antMatchers("/access/user/**").hasRole("USER")
// 进入/access/read/** 需要READ
.antMatchers("/access/read/**").hasRole("READ")
// 进入/access/admin/** 需要ADMIN
.antMatchers("/access/admin/**").hasRole("ADMIN")
//其余请求都需要登录 不限制角色
.anyRequest().authenticated()
// and() 表示上面的配置已经配置完了
.and()
//以表单的方式提交
.formLogin();
}
}
4.controller层
index后台代码
@Controller
public class LoginController {
@GetMapping("/index")
public String login(){
return "/index.html";
}
}
访问的页面代码
<p>验证访问</p>
<a href="/access/user">验证zs</a> <br/>
<a href="/access/read">验证lisi</a><br/>
<a href="/access/admin">验证admin</a><br/>
<a href="/logout" >退出系统</a>
页面
后台
@RestController
public class MyController {
@GetMapping(value = "/access/user",produces = "text/html;charset=utf-8")
public String sayZSroot(){
return "zs 是 user 角色";
}
@GetMapping(value = "/access/read",produces = "text/html;charset=utf-8")
public String sayLSroot(){
return "ls 是 read 角色";
}
@GetMapping(value = "/access/admin",produces = "text/html;charset=utf-8")
public String sayWWadmin(){
return "ww 是 admin 角色";
}
}
5.service层
@Service
public class JDBCUserDetailsService implements UserDetailsService {
@Autowired
private RoleMapper roleMapper;
@Autowired
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//1.根据usernaem获取到 user
User user = userMapper.selectSysUser(username);
System.out.println(user);
if(user!=null){
//根据userid获取到权限
List<Role> roles = roleMapper.selectRoleByUser(user.getId());
System.out.println("roles:"+roles);
//用于存放崇数据库中查询出的权限集合
List<GrantedAuthority> authorities = new ArrayList<>();
for (Role role : roles) {
String name = role.getName();
// "ROLE_"+name 需要添加ROLE_才能识别
GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_"+name);
authorities.add(authority);
}
//把权限集合存入user
user.setAuthorities(authorities);
System.out.println(user);
return user;
}
return null;
}
}
6.mapper层
UserMapper
@Repository//被@Repository注解的类可以自动的被@ComponentScan 通过路径扫描给找到。
public interface UserMapper {
//添加用户信息
int insertSysUser(User user);
//根据账号名称,获取用户信息
User selectSysUser(String username);
}
xml
<?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.abc.mapper.UserMapper">
<!--定义 列和 属性的对应关系-->
<resultMap id="userMapper" type="com.abc.bean.User">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password" />
<result column="realname" property="realname" />
<result column="isenable" property="isEnabled" />
<result column="islock" property="isLocked" />
<result column="iscredentials" property="isCredentials" />
<result column="createtime" property="createTime" />
<result column="logintime" property="loginTime" />
<result column="isexpire" property="isExpired" />
</resultMap>
<!-- 添加用户信息 -->
<insert id="insertSysUser">
insert into sys_user(username,password,realname,
isenable,islock,iscredentials,createtime,logintime)
values(#{username},#{password},#{realname},#{isEnabled},
#{isLocked},#{isCredentials},#{createTime},#{loginTime})
</insert>
<!-- 查询用户信息 -->
<select id="selectSysUser" resultMap="userMapper">
select id, username,password,realname,isexpire,
isenable,islock,iscredentials,createtime,logintime
from sys_user where username=#{username}
</select>
</mapper>
RoleMapper
@Repository//被@Repository注解的类可以自动的被@ComponentScan 通过路径扫描给找到。
public interface RoleMapper {
List<Role> selectRoleByUser(Integer userId);
}
xml
<?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.abc.mapper.RoleMapper">
<!--定义 列和 属性的对应关系-->
<resultMap id="roleMapper" type="com.abc.bean.Role">
<id column="id" property="id"/>
<result column="rolename" property="name"/>
<result column="rolememo" property="memo" />
</resultMap>
<select id="selectRoleByUser" resultMap="roleMapper">
select r.id, r.rolename,r.rolememo from sys_user_role ur , sys_role r
where ur.roleid = r.id and ur.userid=#{userid}
</select>
</mapper>