JwtUser JwtAuthenticationEntryPoint JwtAuthorizationTokenFilter JwtUserDetailsService AuthenticationController
package me.zhengjie.core.security; import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails; import java.sql.Timestamp;
import java.util.*; /**
* @author jie
* @date 2018-11-23
*/
@Getter
@AllArgsConstructor
public class JwtUser implements UserDetails { @JsonIgnore
private final Long id; private final String username; @JsonIgnore
private final String password; private final String avatar; private final String email; @JsonIgnore
private final Collection<? extends GrantedAuthority> authorities; private final boolean enabled; private Timestamp createTime; @JsonIgnore
private final Date lastPasswordResetDate; @JsonIgnore
@Override
public boolean isAccountNonExpired() {
return true;
} @JsonIgnore
@Override
public boolean isAccountNonLocked() {
return true;
} @JsonIgnore
@Override
public boolean isCredentialsNonExpired() {
return true;
} @JsonIgnore
@Override
public String getPassword() {
return password;
} @Override
public boolean isEnabled() {
return enabled;
} /**
* 在我们保存权限的时候加上了前缀ROLE_,因此在这里需要处理下数据
* @return
*/
public Collection getRoles() {
Set<String> roles = new LinkedHashSet<>();
for (GrantedAuthority authority : authorities) {
roles.add(authority.getAuthority().substring(5));
}
return roles;
}
}
package me.zhengjie.core.security; import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable; @Component
public class
JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable { private static final long serialVersionUID = -8970718410437077606L; @Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException {
/**
* 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应
*/
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException==null?"Unauthorized":authException.getMessage());
}
}
package me.zhengjie.core.security; import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable; @Component
public class
JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable { private static final long serialVersionUID = -8970718410437077606L; @Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException {
/**
* 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应
*/
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException==null?"Unauthorized":authException.getMessage());
}
}
package me.zhengjie.core.security; import io.jsonwebtoken.ExpiredJwtException;
import me.zhengjie.core.utils.JwtTokenUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; @Component
public class JwtAuthorizationTokenFilter extends OncePerRequestFilter { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final UserDetailsService userDetailsService;
private final JwtTokenUtil jwtTokenUtil;
private final String tokenHeader; public JwtAuthorizationTokenFilter(@Qualifier("jwtUserDetailsService") UserDetailsService userDetailsService, JwtTokenUtil jwtTokenUtil, @Value("${jwt.header}") String tokenHeader) {
this.userDetailsService = userDetailsService;
this.jwtTokenUtil = jwtTokenUtil;
this.tokenHeader = tokenHeader;
} @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
logger.debug("processing authentication for '{}'", request.getRequestURL()); final String requestHeader = request.getHeader(this.tokenHeader); String username = null;
String authToken = null;
if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
authToken = requestHeader.substring(7);
try {
username = jwtTokenUtil.getUsernameFromToken(authToken);
} catch (ExpiredJwtException e) {
logger.error(e.getMessage());
}
} logger.debug("checking authentication for user '{}'", username); if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
logger.debug("security context was null, so authorizating user"); // It is not compelling necessary to load the use details from the database. You could also store the information
// in the token and read it from it. It's up to you ;)
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); // For simple validation it is completely sufficient to just check the token integrity. You don't have to call
// the database compellingly. Again it's up to you ;)
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
logger.info("authorizated user '{}', setting security context", username);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
chain.doFilter(request, response);
}
}
package me.zhengjie.core.service; import me.zhengjie.common.exception.EntityNotFoundException;
import me.zhengjie.common.utils.ValidationUtil;
import me.zhengjie.core.security.JwtUser;
import me.zhengjie.system.domain.Permission;
import me.zhengjie.system.domain.Role;
import me.zhengjie.system.domain.User;
import me.zhengjie.system.repository.PermissionRepository;
import me.zhengjie.system.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors; /**
* @author jie
* @date 2018-11-22
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class JwtUserDetailsService implements UserDetailsService { @Autowired
private UserRepository userRepository; @Autowired
private PermissionRepository permissionRepository; @Override
public UserDetails loadUserByUsername(String username){ User user = null;
if(ValidationUtil.isEmail(username)){
user = userRepository.findByEmail(username);
} else {
user = userRepository.findByUsername(username);
} if (user == null) {
throw new EntityNotFoundException(User.class, "name", username);
} else {
return create(user);
}
} public UserDetails create(User user) {
return new JwtUser(
user.getId(),
user.getUsername(),
user.getPassword(),
user.getAvatar(),
user.getEmail(),
mapToGrantedAuthorities(user.getRoles(),permissionRepository),
user.getEnabled(),
user.getCreateTime(),
user.getLastPasswordResetTime()
);
} private static List<GrantedAuthority> mapToGrantedAuthorities(Set<Role> roles,PermissionRepository permissionRepository) { Set<Permission> permissions = new HashSet<>();
for (Role role : roles) {
Set<Role> roleSet = new HashSet<>();
roleSet.add(role);
permissions.addAll(permissionRepository.findByRoles(roleSet));
} return permissions.stream()
.map(permission -> new SimpleGrantedAuthority("ROLE_"+permission.getName()))
.collect(Collectors.toList());
}
}
package me.zhengjie.core.service; import me.zhengjie.common.exception.EntityNotFoundException;
import me.zhengjie.common.utils.ValidationUtil;
import me.zhengjie.core.security.JwtUser;
import me.zhengjie.system.domain.Permission;
import me.zhengjie.system.domain.Role;
import me.zhengjie.system.domain.User;
import me.zhengjie.system.repository.PermissionRepository;
import me.zhengjie.system.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors; /**
* @author jie
* @date 2018-11-22
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class JwtUserDetailsService implements UserDetailsService { @Autowired
private UserRepository userRepository; @Autowired
private PermissionRepository permissionRepository; @Override
public UserDetails loadUserByUsername(String username){ User user = null;
if(ValidationUtil.isEmail(username)){
user = userRepository.findByEmail(username);
} else {
user = userRepository.findByUsername(username);
} if (user == null) {
throw new EntityNotFoundException(User.class, "name", username);
} else {
return create(user);
}
} public UserDetails create(User user) {
return new JwtUser(
user.getId(),
user.getUsername(),
user.getPassword(),
user.getAvatar(),
user.getEmail(),
mapToGrantedAuthorities(user.getRoles(),permissionRepository),
user.getEnabled(),
user.getCreateTime(),
user.getLastPasswordResetTime()
);
} private static List<GrantedAuthority> mapToGrantedAuthorities(Set<Role> roles,PermissionRepository permissionRepository) { Set<Permission> permissions = new HashSet<>();
for (Role role : roles) {
Set<Role> roleSet = new HashSet<>();
roleSet.add(role);
permissions.addAll(permissionRepository.findByRoles(roleSet));
} return permissions.stream()
.map(permission -> new SimpleGrantedAuthority("ROLE_"+permission.getName()))
.collect(Collectors.toList());
}
}
package me.zhengjie.core.rest; import lombok.extern.slf4j.Slf4j;
import me.zhengjie.common.aop.log.Log;
import me.zhengjie.core.security.AuthenticationToken;
import me.zhengjie.core.security.AuthorizationUser;
import me.zhengjie.core.utils.JwtTokenUtil;
import me.zhengjie.core.security.JwtUser;
import me.zhengjie.core.utils.EncryptUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest; /**
* @author jie
* @date 2018-11-23
* 授权、根据token获取用户详细信息
*/
@Slf4j
@RestController
@RequestMapping("auth")
public class AuthenticationController { @Value("${jwt.header}")
private String tokenHeader; @Autowired
private AuthenticationManager authenticationManager; @Autowired
private JwtTokenUtil jwtTokenUtil; @Autowired
@Qualifier("jwtUserDetailsService")
private UserDetailsService userDetailsService; /**
* 登录授权
* @param authorizationUser
* @return
*/
@Log(description = "用户登录")
@PostMapping(value = "${jwt.auth.path}")
public ResponseEntity<?> authenticationLogin(@RequestBody AuthorizationUser authorizationUser){ final UserDetails userDetails = userDetailsService.loadUserByUsername(authorizationUser.getUsername()); if(!userDetails.getPassword().equals(EncryptUtils.encryptPassword(authorizationUser.getPassword()))){
throw new AccountExpiredException("密码错误");
} if(!userDetails.isEnabled()){
throw new AccountExpiredException("账号已停用,请联系管理员");
} // 生成令牌
final String token = jwtTokenUtil.generateToken(userDetails); // 返回 token
return ResponseEntity.ok(new AuthenticationToken(token));
} /**
* 获取用户信息
* @param request
* @return
*/
@GetMapping(value = "${jwt.auth.account}")
public ResponseEntity getUserInfo(HttpServletRequest request){
JwtUser jwtUser = (JwtUser)userDetailsService.loadUserByUsername(jwtTokenUtil.getUserName(request));
return ResponseEntity.ok(jwtUser);
}
}
package me.zhengjie.core.security; import lombok.AllArgsConstructor;
import lombok.Getter;
import java.io.Serializable; /**
* @author jie
* @date 2018-11-23
* 返回token
*/
@Getter
@AllArgsConstructor
public class AuthenticationToken implements Serializable { private final String token;
}
package me.zhengjie.core.security; import lombok.Getter;
import lombok.Setter; import javax.validation.constraints.NotBlank; /**
* @author jie
* @date 2018-11-30
*/
@Getter
@Setter
public class AuthorizationUser { @NotBlank
private String username; @NotBlank
private String password; @Override
public String toString() {
return "{username=" + username + ", password= ******}";
}
}
JwtUser JwtAuthenticationEntryPoint JwtAuthorizationTokenFilter JwtUserDetailsService AuthenticationController的更多相关文章
- SpringBoot+SpringSecurity+jwt整合及初体验
原来一直使用shiro做安全框架,配置起来相当方便,正好有机会接触下SpringSecurity,学习下这个.顺道结合下jwt,把安全信息管理的问题扔给客户端, 准备 首先用的是SpringBoot, ...
- 轻松上手SpringBoot Security + JWT Hello World示例
前言 在本教程中,我们将开发一个Spring Boot应用程序,该应用程序使用JWT身份验证来保护公开的REST API.在此示例中,我们将使用硬编码的用户和密码进行用户身份验证. 在下一个教程中,我 ...
- WebSecurityConfig
package me.zhengjie.core.config; import me.zhengjie.core.security.JwtAuthenticationEntryPoint; impor ...
- springboot2.0 web 开发标准目录架构
├── clean-run.sh ├── logs/ 日志文件目录 │ ├── sb2-web_test_2018-06-02_0959.0.log │ └── sb2-web_test.log | ...
- JWT和Spring Security集成
通常情况下,把API直接暴露出去是风险很大的, 我们一般需要对API划分出一定的权限级别,然后做一个用户的鉴权,依据鉴权结果给予用户对应的API (一)JWT是什么,为什么要使用它? 互联网服务离不开 ...
- Spring Boot Security And JSON Web Token
Spring Boot Security And JSON Web Token 说明 流程说明 何时生成和使用jwt,其实我们主要是token更有意义并携带一些信息 https://github.co ...
- Spring Boot 使用 JWT 进行身份和权限验证
上周写了一个 适合初学者入门 Spring Security With JWT 的 Demo,这篇文章主要是对代码中涉及到的比较重要的知识点的说明. 适合初学者入门 Spring Security W ...
- Spring Boot Security JWT 整合实现前后端分离认证示例
前面两章节我们介绍了 Spring Boot Security 快速入门 和 Spring Boot JWT 快速入门,本章节使用 JWT 和 Spring Boot Security 构件一个前后端 ...
- VerificationCodeService
package me.zhengjie.system.domain; import lombok.AllArgsConstructor; import lombok.Data; import lomb ...
随机推荐
- Java IO流操作 (II)
缓冲流 /* * BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符.数组和字符串的高效写入. * BufferedReader:从字符输入流中读取文本,缓冲各个字符, ...
- ZOJ 3757 Alice and Bod 模拟
上次的ZJU月赛题,规则比较复杂,当时就连题意都没摸清楚,只觉得非常复杂 比完后敲啊敲啊敲,连续WA啊,该反思下自己,没按照题意来设置条件,题目中说了 白球入袋并且... 给对手加分 ,白球未入袋并且 ...
- Linux高性能服务器编程:高性能服务器程序框架
服务器有三个主要模块: (1)I/O处理单元 (2)逻辑单元 (3)存储单元 1.服务器模型 C/S模型 逻辑:服务器启动后,首先创建一个或多个监听socket,并调用bind函数将其绑定到服务器感兴 ...
- 1.4CAD2017绘图基础
1.新建(ctrl+n) 命令:new 回车——默认样板(acadiso.dwt) 2.打开(ctr+o) 3.保存(ctrl+S) 4.鼠标的应用: 左键:点击拖选等: 中间滚轮:a.滚动,放大缩小 ...
- 吴裕雄--天生自然MySQL学习笔记:MySQL GROUP BY 语句
GROUP BY 语句根据一个或多个列对结果集进行分组. 在分组的列上我们可以使用 COUNT, SUM, AVG,等函数. GROUP BY 语法 SELECT column_name, funct ...
- Go-并发和并行-协程-信道-缓冲信道-select-mutex-读写文件-beego框架
并发 Go 是并发式语言,而不是并行式语言.在讨论 Go 如何处理并发之前,我们必须理解何为并发,以及并发与并行的区别. 并发是什么? 并发是指立即处理多个任务的能力.一个CPU的情况下<意指看 ...
- h5-携程页面小案例-伸缩盒子
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- leetcode 690.员工的重要性
题目: 给定一个保存员工信息的数据结构,它包含了员工唯一的id,重要度 和 直系下属的id. 比如,员工1是员工2的领导,员工2是员工3的领导.他们相应的重要度为15, 10, 5.那么员工1的数据结 ...
- jquery时钟
<script type="text/javascript"> function getDate(){ var mydate = new Date(); //时间对象 ...
- Cannot find tomcat目录/bin/setclasspath.sh This file is needed to run this program
首先如果直接使用 root 用户来启动 tomcat 的话,是可以正常启动的. 但是我们在 Linux 中使用普通用户启动 tomcat 报了如下错误 Cannot find /developer/a ...