Java用户名密码登录,返回一个token,编写一个过滤器拦截
时间: 2023-12-10 20:41:31 浏览: 28
好的,我可以给你提供一个简单的示例代码来演示如何实现Java用户名密码登录并返回token,以及如何编写一个过滤器拦截。
首先,我们可以使用Spring Security框架来实现用户认证和授权功能。下面是一个简单的示例代码:
```
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/authenticate").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
}
}
```
上面的代码中,我们定义了一个Spring Security的配置类,并且通过@EnableWebSecurity注解启用了Spring Security。在configure方法中,我们定义了用户认证和授权的规则,其中使用了一个UserService来获取用户信息,以及一个BCryptPasswordEncoder来加密密码。在configure(HttpSecurity http)方法中,我们定义了哪些请求需要进行认证,哪些请求可以匿名访问,以及在认证成功之后需要添加一个JwtRequestFilter来生成token。
下面是一个UserService的示例代码:
```
@Service
public class UserService 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<>());
}
}
```
上面的代码中,我们定义了一个UserService,它实现了UserDetailsService接口,用于获取用户信息。在loadUserByUsername方法中,我们通过用户名从数据库中获取用户的信息,并返回一个Spring Security的UserDetails对象。
下面是一个JwtRequestFilter的示例代码:
```
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private UserService userService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String requestTokenHeader = request.getHeader("Authorization");
String username = null;
String jwtToken = null;
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
jwtToken = requestTokenHeader.substring(7);
try {
username = jwtTokenUtil.getUsernameFromToken(jwtToken);
} catch (IllegalArgumentException e) {
logger.error("Unable to get JWT Token");
} catch (ExpiredJwtException e) {
logger.error("JWT Token has expired");
}
} else {
logger.warn("JWT Token does not begin with Bearer String");
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
```
上面的代码中,我们定义了一个JwtRequestFilter,它继承了Spring Security的OncePerRequestFilter,并重写了doFilterInternal方法,在该方法中,我们从请求头中获取token,并使用JwtTokenUtil来验证token的有效性,并将用户信息存储到Spring Security的上下文中。最后,我们通过chain.doFilter(request, response)将请求继续传递给下一个过滤器或处理器。
最后,我们可以编写一个基于注解的控制器来处理用户登录请求:
```
@RestController
@RequestMapping("/api")
public class AuthenticationController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private UserService userService;
@PostMapping("/authenticate")
public ResponseEntity<?> createAuthenticationToken(@RequestBody AuthenticationRequest authenticationRequest)
throws Exception {
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
authenticationRequest.getUsername(), authenticationRequest.getPassword()));
} catch (BadCredentialsException e) {
throw new Exception("Incorrect username or password", e);
}
final UserDetails userDetails = userService.loadUserByUsername(authenticationRequest.getUsername());
final String token = jwtTokenUtil.generateToken(userDetails);
return ResponseEntity.ok(new AuthenticationResponse(token));
}
}
```
上面的代码中,我们定义了一个AuthenticationController,它包含一个createAuthenticationToken方法,用于处理用户登录请求。在该方法中,我们使用AuthenticationManager来验证用户名和密码的正确性,如果验证成功,则生成一个token并将其返回给客户端。
最后,我们可以编写一个过滤器来拦截所有请求,并检查token的有效性:
```
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private UserService userService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String requestTokenHeader = request.getHeader("Authorization");
String username = null;
String jwtToken = null;
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
jwtToken = requestTokenHeader.substring(7);
try {
username = jwtTokenUtil.getUsernameFromToken(jwtToken);
} catch (IllegalArgumentException e) {
logger.error("Unable to get JWT Token");
} catch (ExpiredJwtException e) {
logger.error("JWT Token has expired");
}
} else {
logger.warn("JWT Token does not begin with Bearer String");
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
```
上面的代码中,我们定义了一个JwtAuthenticationFilter,它继承了Spring Security的OncePerRequestFilter,并重写了doFilterInternal方法,在该方法中,我们从请求头中获取token,并使用JwtTokenUtil来验证token的有效性,并将用户信息存储到Spring Security的上下文中。最后,我们通过chain.doFilter(request, response)将请求继续传递给下一个过滤器或处理器。
最后,我们可以在WebSecurityConfig类中注册JwtAuthenticationFilter过滤器:
```
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
// ...
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/authenticate").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
// ...
}
```
上面的代码中,我们在configure(HttpSecurity http)方法中注册了JwtAuthenticationFilter过滤器,用于拦截所有请求并检查token的有效性。