218.Spring Boot+Spring Security:基于内存数据库的身份认证和角色授权
Posted SpringBoot
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了218.Spring Boot+Spring Security:基于内存数据库的身份认证和角色授权相关的知识,希望对你有一定的参考价值。
说明
(1)JDK版本:1.8
(2)Spring Boot 2.0.6
(3)Spring Security 5.0.9
(4)Spring Data JPA 2.0.11.RELEASE
(5)hibernate5.2.17.Final
(6)hsqldb2.4.1
需求缘起
在前面我们使用基于内存的方式体验了下Spring Security,在实际项目中,都是需要数据库进行操作的,本节使用hsqldb内存数据库进行说明。
编码思路
这里我们使用的是Spring Data JPA进行操作数据库,所以需要添加相关的依赖;其次就是需要定义一个保存用户基本的实体类;再者需要定义相应的服务获取用户的信息;最后重写UserDetailsService的loadUserByUsername方法从数据库中获取用户信息,传给Spring Security进行处理。
一、基于内存数据库的身份认证和角色授权
1.1 添加依赖
在pom.xml文件中添加SpringData JPA和hsqldb的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
1.2 创建实体类
创建UserInfo实体类:
package com.kfit.permission.bean;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class UserInfo {
public enum Role{
admin,normal
}
@Id @GeneratedValue
private long uid;//主键.
private String username;//用户名.
private String password;//密码.
@Enumerated(EnumType.STRING)
private Role role;
public long getUid() {
return uid;
}
public void setUid(long uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
}
1.3 创建Repository
创建和数据库交互的UserInfoRepository:
package com.kfit.permission.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.kfit.permission.bean.UserInfo;
public interface UserInfoRepository extends JpaRepository<UserInfo,Long> {
public UserInfo findByUsername(String username);
}
1.4 创建Service
创建UserInfoService:
package com.kfit.permission.service;
import com.kfit.permission.bean.UserInfo;
public interface UserInfoService {
public UserInfo findByUsername(String username);
}
创建UserInfoService的实现类:
package com.kfit.permission.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.kfit.permission.bean.UserInfo;
import com.kfit.permission.repository.UserInfoRepository;
import com.kfit.permission.service.UserInfoService;
@Service
public class UserInfoServiceImpl implements UserInfoService {
@Autowired
private UserInfoRepository userInfoRepository;
@Override
public UserInfo findByUsername(String username) {
return userInfoRepository.findByUsername(username);
}
}
1.5 自定义UserDetailsService
自定义一个UserDetailsService,取名为CustomUserDetailService,该类需要实现接口UserDetailsService,主要是实现loadUserByUsername方法:
package com.kfit.config;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
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.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import com.kfit.permission.bean.UserInfo;
import com.kfit.permission.service.UserInfoService;
@Component
public class CustomUserDetailService implements UserDetailsService{
@Autowired
private UserInfoService userInfoService;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("CustomUserDetailService.loadUserByUsername()");
//通过username获取用户信息
UserInfo userInfo = userInfoService.findByUsername(username);
if(userInfo == null) {
throw new UsernameNotFoundException("not found");
}
//定义权限列表.
List<GrantedAuthority> authorities = new ArrayList<>();
// 用户可以访问的资源名称(或者说用户所拥有的权限) 注意:必须"ROLE_"开头
authorities.add(new SimpleGrantedAuthority("ROLE_"+userInfo.getRole().name()));
User userDetails = new User(userInfo.getUsername(),passwordEncoder.encode(userInfo.getPassword()),authorities);
return userDetails;
}
}
说明:
(1) 通过username获取用户的信息。
(2) 定义一个User(实现了接口UserDetails)对象,返回用户的username,passowrd和权限列表。
(3) 需要注意,定义角色集的时候,需要添加前缀“ROLE_”。
(4) 这里的密码需要使用PasswordEncoder进行加密,否则会报“无效的凭证”。
1.6 初始化测试账号
这里我们使用一个DataInit类,初始化两个账号admin/123和user/123:
package com.kfit.permission.init;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.kfit.permission.bean.UserInfo;
import com.kfit.permission.bean.UserInfo.Role;
import com.kfit.permission.repository.UserInfoRepository;
@Service
public class DataInit {
@Autowired UserInfoRepository userInfoRepository;
@PostConstruct
public void dataInit() {
UserInfo admin = new UserInfo();
admin.setUsername("admin");
admin.setPassword("123");
admin.setRole(Role.admin);
userInfoRepository.save(admin);
UserInfo user = new UserInfo();
user.setUsername("user");
user.setPassword("123");
user.setRole(Role.normal);
userInfoRepository.save(user);
}
}
1.7 启动测试
(1)测试账号:user/123
http://127.0.0.1:8080/hello/helloUser
自动跳转到登录页面,输入账号user/123,可以看到页面:
http://127.0.0.1:8080/hello/helloAdmin
访问被拒绝:
(2)测试账号:admin/123
历史文章
à悟空学院:http://t.cn/Rg3fKJD
学院中有Spring Boot相关的课程!点击「阅读原文」进行查看!
SpringBoot视频:http://t.cn/R3QepWG
Spring Cloud视频:http://t.cn/R3QeRZc
SpringBoot Shiro视频:http://t.cn/R3QDMbh
SpringBoot交流平台:http://t.cn/R3QDhU0
SpringData和JPA视频:http://t.cn/R1pSojf
SpringSecurity5.0视频:http://t.cn/EwlLjHh
以上是关于218.Spring Boot+Spring Security:基于内存数据库的身份认证和角色授权的主要内容,如果未能解决你的问题,请参考以下文章
Spring boot??????????????????Spring boot??????MySql,Mybatis???PageHelper??????