# 《基于Spring Security和 JWT的权限系统设计》
---
![Profile](https://upload-images.jianshu.io/upload_images/9824247-a96eacce43460601.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
---
## 写在前面
- **关于 Spring Security**
Web系统的认证和权限模块也算是一个系统的基础设施了,几乎任何的互联网服务都会涉及到这方面的要求。在Java EE领域,成熟的安全框架解决方案一般有 Apache Shiro、Spring Security等两种技术选型。Apache Shiro简单易用也算是一大优势,但其功能还是远不如 Spring Security强大。Spring Security可以为 Spring 应用提供声明式的安全访问控制,起通过提供一系列可以在 Spring应用上下文中可配置的Bean,并利用 Spring IoC和 AOP等功能特性来为应用系统提供声明式的安全访问控制功能,减少了诸多重复工作。
- **关于JWT**
JSON Web Token (JWT),是在网络应用间传递信息的一种基于 JSON的开放标准((RFC 7519),用于作为JSON对象在不同系统之间进行安全地信息传输。主要使用场景一般是用来在 身份提供者和服务提供者间传递被认证的用户身份信息。关于JWT的科普,可以看看阮一峰老师的《JSON Web Token 入门教程》。
本文则结合 Spring Security和 JWT两大利器来打造一个简易的权限系统。
本文实验环境如下:
- Spring Boot版本:`2.0.6.RELEASE`
- IDE:`IntelliJ IDEA 2018.2.4`
>另外本文实验代码置于文尾,需要自取。
> 可 **长按** 或 **扫描** 下面的 **小心心** 来订阅作者公众号 **CodeSheep**,获取更多 **务实、能看懂、可复现的** 原创文 ↓↓↓
![CodeSheep · 程序羊](https://user-gold-cdn.xitu.io/2018/8/9/1651c0ef66e4923f?w=270&h=270&f=png&s=102007)
---
## 设计用户和角色
本文实验为了简化考虑,准备做如下设计:
- 设计一个最简角色表`role`,包括`角色ID`和`角色名称`
![角色表](https://upload-images.jianshu.io/upload_images/9824247-d24b696799ced559.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- 设计一个最简用户表`user`,包括`用户ID`,`用户名`,`密码`
![用户表](https://upload-images.jianshu.io/upload_images/9824247-a56eb9ed64bee618.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- 再设计一个用户和角色一对多的关联表`user_roles`
一个用户可以拥有多个角色
![用户-角色对应表](https://upload-images.jianshu.io/upload_images/9824247-d14f07e1ae45e6fc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
---
## 创建 Spring Security和 JWT加持的 Web工程
- **`pom.xml` 中引入 Spring Security和 JWT所必需的依赖**
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
```
- **项目配置文件中加入数据库和 JPA等需要的配置**
```
server.port=9991
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://121.196.XXX.XXX:3306/spring_security_jwt?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=XXXXXX
logging.level.org.springframework.security=info
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jackson.serialization.indent_output=true
```
- **创建用户、角色实体**
**用户实体 User**:
```java
/**
* @ www.codesheep.cn
* 20190312
*/
@Entity
public class User implements UserDetails {
@Id
@GeneratedValue
private Long id;
private String username;
private String password;
@ManyToMany(cascade = {CascadeType.REFRESH},fetch = FetchType.EAGER)
private List<Role> roles;
...
// 下面为实现UserDetails而需要的重写方法!
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities = new ArrayList<>();
for (Role role : roles) {
authorities.add( new SimpleGrantedAuthority( role.getName() ) );
}
return authorities;
}
...
}
```
此处所创建的 User类继承了 Spring Security的 UserDetails接口,从而成为了一个符合 Security安全的用户,即通过继承 UserDetails,即可实现 Security中相关的安全功能。
**角色实体 Role:**
```java
/**
* @ www.codesheep.cn
* 20190312
*/
@Entity
public class Role {
@Id
@GeneratedValue
private Long id;
private String name;
... // 省略 getter和 setter
}
```
- **创建JWT工具类**
主要用于对 JWT Token进行各项操作,比如生成Token、验证Token、刷新Token等
```java
/**
* @ www.codesheep.cn
* 20190312
*/
@Component
public class JwtTokenUtil implements Serializable {
private static final long serialVersionUID = -5625635588908941275L;
private static final String CLAIM_KEY_USERNAME = "sub";
private static final String CLAIM_KEY_CREATED = "created";
public String generateToken(UserDetails userDetails) {
...
}
String generateToken(Map<String, Object> claims) {
...
}
public String refreshToken(String token) {
...
}
public Boolean validateToken(String token, UserDetails userDetails) {
...
}
... // 省略部分工具函数
}
```
- **创建Token过滤器,用于每次外部对接口请求时的Token处理**
```java
/**
* @ www.codesheep.cn
* 20190312
*/
@Component
public class JwtTokenFilter extends OncePerRequestFilter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
protected void doFilterInternal ( HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
String authHeader = request.getHeader( Const.HEADER_STRING );
if (authHeader != null && authHeader.startsWith( Const.TOKEN_PREFIX )) {
final String authToken = authHeader.substring( Const.TOKEN_PREFIX.length() );
String username = jwtTokenUtil.getUsernameFromToken(authToken);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(
request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
chain.doFilter(request, response);
}
}
```
- **Service业务编写**
主要包括用户登录和注册两个主要的业务
```java
public interface AuthService {
User register( User userToAdd );
String login( String username, String password );
}
```
```java
/**
* @ www.codesheep.cn
* 20190312
*/
@Service
public class AuthServiceImpl implements AuthService {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private UserRepository userRepository;
// 登录
@Override
public String login( String username, String password ) {
UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken( username, password );
final Authentication authentication = authenticationManager.authenticate(upToken);
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
Spring Boot 系列实战合集.zip (236个子文件)
.DS_Store 6KB
.DS_Store 6KB
.DS_Store 6KB
.DS_Store 6KB
.DS_Store 6KB
.DS_Store 6KB
.DS_Store 6KB
.DS_Store 6KB
.DS_Store 6KB
.DS_Store 6KB
.DS_Store 6KB
.DS_Store 6KB
.DS_Store 6KB
spring.factories 141B
.gitignore 268B
.gitignore 268B
.gitignore 268B
build.gradle 1KB
settings.gradle 43B
evcache-client-4.137.0-SNAPSHOT.jar 273KB
maven-wrapper.jar 46KB
maven-wrapper.jar 46KB
maven-wrapper.jar 46KB
vesta-service-0.0.1.jar 38KB
id-spring-boot-starter-1.0.0.jar 34KB
vesta-intf-0.0.1.jar 4KB
RingBuffer.java 10KB
RingBuffer.java 10KB
DefaultUidGenerator.java 8KB
DefaultUidGenerator.java 8KB
CachedUidGenerator.java 7KB
CachedUidGenerator.java 7KB
BufferPaddingExecutor.java 6KB
BufferPaddingExecutor.java 6KB
NamingThreadFactory.java 5KB
NamingThreadFactory.java 5KB
JwtTokenUtil.java 4KB
BitsAllocator.java 4KB
BitsAllocator.java 4KB
CachedUidGeneratorTest.java 4KB
EVCacheClientSample.java 3KB
DefaultUidGeneratorTest.java 3KB
AuthorizationServerConfig.java 3KB
DateUtils.java 3KB
DateUtils.java 3KB
DockerUtils.java 3KB
DockerUtils.java 3KB
ImgWatermarkServiceImpl.java 3KB
WebSecurityConfig.java 3KB
DisposableWorkerIdAssigner.java 3KB
DisposableWorkerIdAssigner.java 3KB
WorkerNodeEntity.java 3KB
WorkerNodeEntity.java 3KB
TestServiceImpl.java 3KB
JwtTokenFilter.java 2KB
NetUtils.java 2KB
NetUtils.java 2KB
SbaServer20Application.java 2KB
AuthServiceImpl.java 2KB
SpringSecurityConfig.java 2KB
User.java 2KB
UidService.java 2KB
UidGenerateException.java 2KB
UidGenerateException.java 2KB
EnumUtils.java 2KB
EnumUtils.java 2KB
PaddedAtomicLong.java 2KB
PaddedAtomicLong.java 2KB
UidController.java 2KB
WatermarkController.java 1KB
EntityController.java 1KB
WorkerNodeDAO.java 1KB
WorkerNodeDAO.java 1KB
UserController.java 1KB
UserController.java 1KB
UserServiceImpl.java 1KB
JwtAuthController.java 1KB
UserController.java 1KB
UidGenerator.java 1KB
UidGenerator.java 1KB
EVCacheTestController.java 1KB
WorkerNodeType.java 1KB
WorkerNodeType.java 1KB
RejectedPutBufferHandler.java 1KB
RejectedPutBufferHandler.java 1KB
RejectedTakeBufferHandler.java 1KB
RejectedTakeBufferHandler.java 1KB
SheepUserDetailsService.java 1KB
UserService.java 1KB
BufferedUidProvider.java 1007B
BufferedUidProvider.java 1007B
ImageUploadService.java 998B
WorkerIdAssigner.java 981B
WorkerIdAssigner.java 981B
ValuedEnum.java 970B
ValuedEnum.java 970B
ClientWebsecurityConfigurer.java 923B
ClientWebsecurityConfigurer.java 923B
TestController.java 892B
UserService.java 891B
共 236 条
- 1
- 2
- 3
资源评论
AbelZ_01
- 粉丝: 875
- 资源: 5441
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功