springboot+springsecurity+jwt+vue
时间: 2023-11-24 21:05:57 浏览: 167
Spring Boot是一个基于Spring框架的快速开发Web应用程序的框架,Spring Security是Spring框架的安全模块,JWT是一种用于身份验证的开放标准。Vue是一种流行的JavaScript框架,用于构建用户界面。
结合这些技术,可以实现前后端分离的登录、权限管理和Token管理。具体步骤如下:
1. 在Spring Boot项目中导入Spring Security和JWT的Maven依赖。
2. 配置Spring Security,包括创建用户、角色和权限等。
3. 创建一个JWT工具类,用于生成和解析Token。
4. 创建一个登录接口,接收用户名和密码,验证用户信息,生成Token并返回给前端。
5. 创建一个Token验证过滤器,用于验证请求中的Token是否有效。
6. 在Vue项目中使用Axios发送登录请求,获取Token并保存到本地存储中。
7. 在Vue项目中使用Vue Router和VueX进行路由和状态管理。
8. 创建一个路由守卫,用于验证用户是否登录和是否有权限访问某些页面。
9. 在需要进行身份验证的请求中添加Token。
下面是一个简单的示例代码,仅供参考:
后端代码:
```java
// 配置Spring Security
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
// 创建一个JWT工具类
public class JwtUtils {
private static final String SECRET_KEY = "mySecretKey";
private static final long EXPIRATION_TIME = 86400000; // 24 hours
public static String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return Jwts.builder()
.setClaims(claims)
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SECRET_KEY)
.compact();
}
public static String getUsernameFromToken(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getSubject();
}
public static boolean validateToken(String token, UserDetails userDetails) {
String username = getUsernameFromToken(token);
return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
}
private static boolean isTokenExpired(String token) {
Date expiration = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getExpiration();
return expiration.before(new Date());
}
}
// 创建一个登录接口
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@PostMapping("/login")
public ResponseEntity<?> authenticateUser(@RequestBody LoginRequest loginRequest) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
UserDetails userDetails = userDetailsService.loadUserByUsername(loginRequest.getUsername());
String token = JwtUtils.generateToken(userDetails);
return ResponseEntity.ok(new JwtAuthenticationResponse(token));
}
}
// 创建一个Token验证过滤器
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtUtils jwtUtils;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String header = request.getHeader("Authorization");
if (header != null && header.startsWith("Bearer ")) {
String token = header.substring(7);
String username = jwtUtils.getUsernameFromToken(token);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtUtils.validateToken(token, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
filterChain.doFilter(request, response);
}
}
// 创建一个自定义的AuthenticationEntryPoint
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}
// 创建一个自定义的UserDetailsService
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found with username: " + username);
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(),
new ArrayList<>());
}
}
// 创建一个实体类User和一个接口UserRepository
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username")
private String username;
@Column(name = "password")
private String password;
// getters and setters
}
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}
```
前端代码:
```javascript
// 在Vue项目中使用Axios发送登录请求
axios.post('/api/auth/login', {
username: 'admin',
password: 'password'
}).then(response => {
localStorage.setItem('token', response.data.token);
});
// 在需要进行身份验证的请求中添加Token
axios.get('/api/users', {
headers: {
Authorization: 'Bearer ' + localStorage.getItem('token')
}
});
// 创建一个路由守卫
router.beforeEach((to, from, next) => {
const publicPages = ['/login', '/register'];
const authRequired = !publicPages.includes(to.path);
const loggedIn = localStorage.getItem('token');
if (authRequired && !loggedIn) {
return next('/login');
}
next();
});
// 使用VueX进行状态管理
const store = new Vuex.Store({
state: {
isLoggedIn: !!localStorage.getItem('token')
},
mutations: {
login(state) {
state.isLoggedIn = true;
},
logout(state) {
state.isLoggedIn = false;
}
},
actions: {
login({ commit }) {
return new Promise(resolve => {
axios.post('/api/auth/login', {
username: 'admin',
password: 'password'
}).then(response => {
localStorage.setItem('token', response.data.token);
commit('login');
resolve();
});
});
},
logout({ commit }) {
return new Promise(resolve => {
localStorage.removeItem('token');
commit('logout');
resolve();
});
}
}
});
```
阅读全文