springboot整合springsecurity实现用户登录校验
springboot项目使用springsecurity+jwt实现用户校验
SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,控制反转,依赖注入和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。(注:此篇为自学springsecurity时的demo,特此记录下来方便日后使用)
业务流程
前端
后端
用户名+密码
验证用户为真,生成jwt令牌
return jwt令牌
携带jwt令牌,访问后台资源
前端
后端
文件目录结构
所需的maven
1. jjwt
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
2.springsecurity
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
核心代码
1.JwtUtil(实现生成jwt和解析jwt)
package com.hnzrbt.controller.utils;
public class JwtUtil {
public static final Long JWT_TTL = 7*24*60*60*1000L;
public static final String JWT_KEY = "xxxxxx";
public static String getUUID(){
return UUID.randomUUID().toString().replaceAll("-","");
}
public static String createJwt(String s){
JwtBuilder builder = getJwtBuilder(s, null, getUUID());
return builder.compact();
}
public static String createJwt(String s , Long ttlMillis){
JwtBuilder builder = getJwtBuilder(s, ttlMillis, getUUID());
return builder.compact();
}
private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
SecretKey secretKey = generalKey();
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
if(ttlMillis==null){
ttlMillis=JwtUtil.JWT_TTL;
}
long expMillis = nowMillis + ttlMillis;
Date expDate = new Date(expMillis);
return Jwts.builder()
.setId(uuid)
.setSubject(subject)
.setIssuer("xxxxxx")
.setIssuedAt(now)
.signWith(signatureAlgorithm, secretKey)
.setExpiration(expDate);
}
public static String createJWT(String id, String subject, Long ttlMillis) {
JwtBuilder builder = getJwtBuilder(subject, ttlMillis, id);
return builder.compact();
}
public static SecretKey generalKey() {
byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
}
public static Claims parseJWT(String jwt) throws Exception {
SecretKey secretKey = generalKey();
return Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(jwt)
.getBody();
}
}
2.SecurityConfig
@Configuration
public class SecurityConfig {
@Autowired
JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity)throws Exception{
httpSecurity
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/companycms/login").anonymous()
.anyRequest().authenticated();
httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
return httpSecurity.build();
}
@Autowired
private AuthenticationConfiguration authenticationConfiguration;
@Bean
public AuthenticationManager authenticationManager() throws Exception{
AuthenticationManager authenticationManager = authenticationConfiguration.getAuthenticationManager();
return authenticationManager;
}
}
3.LoginController
@RestController
@RequestMapping("/companycms")
public class LoginController {
@Autowired
private LoginService loginService;
@PostMapping("login")
public R login(@RequestBody User user){
return loginService.login(user);
}
@PostMapping("logout")
public R logout(){
return loginService.logout();
}
}
4.Dao和DaoImpl
@Mapper
public interface UserDao extends BaseMapper<User> {
}
@Data
public class User {
private Integer id;
private String ucont;
private String upwd;
}
5.LoginService
public interface LoginService {
public R login(User user);
public R logout();
}
6. LoginServiceImpl
package com.hnzrbt.service.impl;
@Service
public class LoginServiceImpl implements LoginService {
@Autowired
AuthenticationManager authenticationManager;
@Autowired
RedisCache redisCache;
@Override
public R login(User user) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(user.getUcont(),user.getUpwd());
Authentication authentication = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
if (Objects.isNull(authentication)){
throw new RuntimeException("用户名或密码错误!");
}
LoginUser loginUser = (LoginUser)(authentication.getPrincipal());
String id = loginUser.getUser().getId().toString();
String jwt = JwtUtil.createJwt(id);
Map<String,String> map = new HashMap();
map.put("token",jwt);
redisCache.setCacheObject("login"+id,loginUser);
return new R(true,map);
}
@Override
public R logout() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
Integer id = loginUser.getUser().getId();
redisCache.deleteObject("login"+id);
return new R(true);
}
}
7.UserDetailServiceImpl
@Service
public class UserDetailServiceImpl implements UserDetailsService {
@Autowired
UserDao userDao;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(User::getUcont,username);
User user = userDao.selectOne(lambdaQueryWrapper);
if (Objects.isNull(user)){
throw new RuntimeException("用户不存在");
}
return new LoginUser(user);
}
}
|