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的更多相关文章

  1. SpringBoot+SpringSecurity+jwt整合及初体验

    原来一直使用shiro做安全框架,配置起来相当方便,正好有机会接触下SpringSecurity,学习下这个.顺道结合下jwt,把安全信息管理的问题扔给客户端, 准备 首先用的是SpringBoot, ...

  2. 轻松上手SpringBoot Security + JWT Hello World示例

    前言 在本教程中,我们将开发一个Spring Boot应用程序,该应用程序使用JWT身份验证来保护公开的REST API.在此示例中,我们将使用硬编码的用户和密码进行用户身份验证. 在下一个教程中,我 ...

  3. WebSecurityConfig

    package me.zhengjie.core.config; import me.zhengjie.core.security.JwtAuthenticationEntryPoint; impor ...

  4. springboot2.0 web 开发标准目录架构

    ├── clean-run.sh ├── logs/ 日志文件目录 │ ├── sb2-web_test_2018-06-02_0959.0.log │ └── sb2-web_test.log | ...

  5. JWT和Spring Security集成

    通常情况下,把API直接暴露出去是风险很大的, 我们一般需要对API划分出一定的权限级别,然后做一个用户的鉴权,依据鉴权结果给予用户对应的API (一)JWT是什么,为什么要使用它? 互联网服务离不开 ...

  6. Spring Boot Security And JSON Web Token

    Spring Boot Security And JSON Web Token 说明 流程说明 何时生成和使用jwt,其实我们主要是token更有意义并携带一些信息 https://github.co ...

  7. Spring Boot 使用 JWT 进行身份和权限验证

    上周写了一个 适合初学者入门 Spring Security With JWT 的 Demo,这篇文章主要是对代码中涉及到的比较重要的知识点的说明. 适合初学者入门 Spring Security W ...

  8. Spring Boot Security JWT 整合实现前后端分离认证示例

    前面两章节我们介绍了 Spring Boot Security 快速入门 和 Spring Boot JWT 快速入门,本章节使用 JWT 和 Spring Boot Security 构件一个前后端 ...

  9. VerificationCodeService

    package me.zhengjie.system.domain; import lombok.AllArgsConstructor; import lombok.Data; import lomb ...

随机推荐

  1. nodejs(14)express获取url中的参数

    问号传参获取参数 获取 http://127.0.0.1:3001/user?id=10&name=zs 中的查询参数: 直接使用 req.query 获取参数即可: 注意:URL 地址栏中通 ...

  2. 运用Access学习数据库的三大范式

    第一范式(1NF):强调的是列的原子性,即“列不能够再分成其他几列”,同一列中不能有多个值. 例子:业余爱好编码表+员工编码表 当员工杨来的业余爱好有多个时,此时的数据库设计不满足第一范式,可进行如下 ...

  3. Dijkstra与Floyd算法

    1. Dijkstra算法 1.1 定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点 ...

  4. Feign整合测试

    1.测试使用 (1)服务调用方引入依赖 <dependency> <groupId>org.springframework.cloud</groupId> < ...

  5. 系统学习python第四天学习笔记

    1.解释 / 编译补充 编译型:代码写完后,编译器将其变成成另外一个文件,然后交给计算机执行. 解释型:写完代码交给解释器,解释器会从上到下一行行代码执行:边解释边执行. [实时翻译] 2.字符串功能 ...

  6. 4418之Android Eclipse导入应用程序在开发板上调试

    由于在开发板上 LEDtest 应用已经默认安装了,所以在开发板上调试已安装应用的时候,需要做一下处理才能够正常连接.基于迅为iTOP4418开发板如下图所示,在打开工程“ledtest”,打开“bi ...

  7. c# 基础switct---case用于处理多条件的定值的判断

    题目:李四的年终工作评定,如果定为A级,则工资涨500元,如果定为B级,则工资涨200元,如果定为C级,工资不变,如果定为D级工资降200元,如果定为E级工资降500元. 设李四原工资为5000,请用 ...

  8. c语言中用简单方法对多维数组进行初始化

    例:int array[4][3] = {1,2,3,4,5,6,7,8,9,10,11,12}; 说明:a.由4*3可知,本二维数组包含12个元素,因此初始化时array[0][0] = 1 ,ar ...

  9. UML-类图-需要写关联名称吗?

    概念模型:需要写关联名称:类图:不需要写关联名称. 注意,概念模型关联线不需要箭头.

  10. Tkinter控件

    1.顶层(Toplevel) Toplevel为其他控件提供单独的容器.共有四种类型(1)主顶层,作为根被应用,应该就是root(2)子顶层,依赖于根,根破坏,子顶层也被破坏(3)临时顶层,画在父顶层 ...