Слияние кода завершено, страница обновится автоматически
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author: Wang Chen Chen
* @Date: 2018/10/29 14:10
* @describe:
* @version: 1.0
*/
@Data
@ConfigurationProperties(prefix = "jwt")
@Component
public class JwtTokenUtil implements Serializable {
private String secret;
private Long expiration;
private String header;
/**
* Из данных декларации генерирует токен
*
* @param claims Данные декларации
* @return Токен
*/
private String generateToken(Map<String, Object> claims) {
Date expirationDate = new Date(System.currentTimeMillis() + expiration);
return Jwts.builder().setClaims(claims).setExpiration(expirationDate).signWith(SignatureAlgorithm.HS512, secret).compact();
}
/**
* Получает данные декларации из токена
*
* @param token Токен
* @return Данные декларации
*/
private Claims getClaimsFromToken(String token) {
Claims claims;
try {
claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
} catch (Exception e) {
claims = null;
}
return claims;
}
/**
* Генерирует токен из данных пользователя
*
* @param userDetails Пользователь
* @return Токен
*/
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>(2);
claims.put("sub", userDetails.getUsername());
claims.put("created", new Date());
return generateToken(claims);
}
/**
* Получает имя пользователя из токена
*
* @param token Токен
* @return Имя пользователя
*/
public String getUsernameFromToken(String token) {
String username;
try {
Claims claims = getClaimsFromToken(token);
username = claims.getSubject();
} catch (Exception e) {
username = null;
}
return username;
}
/**
* Проверяет, не истёк ли срок действия токена
*
* @param token Токен
* @return Истек ли срок действия
*/
public Boolean isTokenExpired(String token) {
try {
Claims claims = getClaimsFromToken(token);
Date expiration = claims.getExpiration();
return expiration.before(new Date());
} catch (Exception e) {
return false;
}
}
/**
* Обновляет токен
*
* @param token Исходный токен
* @return Новый токен
*/
public String refreshToken(String token) {
String refreshedToken;
try {
Claims claims = getClaimsFromToken(token);
claims.put("created", new Date());
refreshedToken = generateToken(claims);
} catch (Exception e) {
refreshedToken = null;
}
return refreshedToken;
}
/**
* Проверяет токен
*
* @param token Токен
* @param userDetails Данные пользователя
* @return Действительно ли токен валиден
*/
public Boolean validateToken(String token, UserDetails userDetails) {
JwtUser user = (JwtUser) userDetails;
String username = getUsernameFromToken(token);
return (username.equals(user.getUsername()) && !isTokenExpired(token));
}
}
``` **Перевод текста на русский язык:**
javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author: Wang Chen Chen
* @Date: 2018/10/29 14:29
* @describe:
* @version: 1.0
*/
@Slf4j
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
// 从这里开始获取 request 中的 jwt token
String authHeader = request.getHeader(jwtTokenUtil.getHeader());
log.info("authHeader:{}", authHeader);
// 验证token是否存在
if (authHeader != null && StringUtils.isNotEmpty(authHeader)) {
// 根据token 获取用户名
String username = jwtTokenUtil.getUsernameFromToken(authHeader);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
// 通过用户名 获取用户的信息
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
// 验证token和用户是否匹配
if (jwtTokenUtil.validateToken(authHeader, userDetails)) {
// 然后把构造UsernamePasswordAuthenticationToken对象
// 最后绑定到当前request中,在后面的请求中就可以获取用户信息
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
chain.doFilter(request, response);
}
}
### **Реализация spring Security UserDetailsService интерфейса**
```java
package com.ifsaid.admin.service.impl;
import com.ifsaid.admin.common.jwt.JwtUser;
import com.ifsaid.admin.entity.SysRole;
import com.ifsaid.admin.entity.SysUser;
import com.ifsaid.admin.mapper.SysUserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author: Wang Chen Chen
* @Date: 2018/10/29 14:15
* @describe:
* @version: 1.0
*/
@Slf4j
@Service
public class JwtUserDetailsServiceImpl implements UserDetailsService {
@Autowired
private SysUserMapper sysUserMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 根据用户名获取数据库的用户信息
SysUser sysUser = sysUserMapper.selectByUserName(username);
if (sysUser == null || StringUtils.isEmpty(sysUser.getUid())) {
throw new UsernameNotFoundException(String.format("'%s'.这个用户不存在", username));
} else {
// 根据数据库中的用户信息,构建JwtUser对象
List<SimpleGrantedAuthority> collect = sysUser.getRoles().stream().map(SysRole::getName).map(SimpleGrantedAuthority::new).collect(Collectors.toList());
return new JwtUser(sysUser.getUsername(), sysUser.getPassword(), sysUser.getState(), collect);
}
}
}
### **Конфигурация spring Security**
```java
package com.ifsaid.admin.config;
import com.ifsaid.admin.common.jwt.JwtAuthenticationTokenFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import
*Здесь текст обрывается.* Роль.getPermissions().forEach(разрешение -> {
if (permission.getType().toLowerCase().equals("button")) {
/*
* Если разрешение является кнопкой, то добавляем его в кнопки
*/
buttonVos.add(new ButtonVo(permission.getPid(), permission.getResources(), permission.getTitle()));
}
if (permission.getType().toLowerCase().equals("menu")) {
/*
* Если разрешение является меню, то добавляем его в меню
*/
menuVos.add(new MenuVo(permission.getPid(), permission.getFather(), permission.getIcon(), permission.getResources(), permission.getTitle()));
}
});
/**
* Обратите внимание на этот класс TreeBuilder. Поскольку vue router представляет меню в рекурсивной форме,
* нам нужно сопоставить меню с форматом vue router один к одному, а кнопки не нужны.
*/
SysUserVo sysUserVo = new SysUserVo(sysUser.getUid(), sysUser.getAvatar(),
sysUser.getNickname(), sysUser.getUsername(),
sysUser.getMail(), sysUser.getAddTime(),
sysUser.getRoles(), buttonVos, TreeBuilder.findRoots(menuVos));
return sysUserVo;
}
// Если в WebSecurityConfigurerAdapter нет повторной настройки, здесь будет выдано исключение внедрения
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private PasswordEncoder passwordEncoder;
override public String login(String username, String password) {
UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken(username, password);
Authentication authentication = authenticationManager.authenticate(upToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
return jwtTokenUtil.generateToken(userDetails);
}
override public Integer register(SysUser sysUser) throws UserExistsException {
String username = sysUser.getUsername();
if (findByUsername(username) != null) {
throw new UserExistsException(String.format("'%s' 这个用用户已经存在了", username));
}
String rawPassword = sysUser.getPassword();
sysUser.setPassword(passwordEncoder.encode(rawPassword));
sysUser.setUpTime(new Date());
sysUser.setAddTime(new Date());
return baseMapper.insertSelective(sysUser);
}
override public String refreshToken(String oldToken) {
if (!jwtTokenUtil.isTokenExpired(oldToken)) {
return jwtTokenUtil.refreshToken(oldToken);
}
return "error";
}
Контроллер для входа и обновления токена
package com.ifsaid.admin.controller;
import com.ifsaid.admin.service.ISysUserService;
import com.ifsaid.admin.vo.Result;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* @author: Wang Chen Chen
* @Date: 2018/10/29 10:49
* @describe:
* @version: 1.0
*/
@RestController
public class AuthController {
@Autowired
private ISysUserService sysUserService;
@PostMapping(value = "${jwt.route.login}")
public Result<String> login(@RequestBody Map<String, String> map) {
String username = map.get("username");
String password = map.get("password");
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
return Result.error401("用户或者密码不能为空!", null);
}
return Result.success("登录成功", sysUserService.login(username, password));
}
@PostMapping(value = "${jwt.route.refresh}")
public Result<String> refresh(@RequestHeader("${jwt.header}") String token) {
return Result.success("刷新token成功!", sysUserService.refreshToken(token));
}
}
Здесь мы уже получили токен.
Затем, используя токен, получаем информацию о пользователе.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )