java Spring Security服务配置

8aqjt8rx  于 2023-05-27  发布在  Java
关注(0)|答案(2)|浏览(131)

我正在尝试使用不同的框架构建一个Java EE应用程序原型。除了安全层,一切都很好。我选择了使用Spring配置来配置Spring Security。
代码如下:

Spring安全配置

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
    @Autowired
    private MyUserDetailsService userDetailsService;

    @Override
    protected UserDetailsService userDetailsService () {
        return this.userDetailsService;
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web
        .ignoring()
        .antMatchers("/resources/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .formLogin()
        .loginPage("/login")
        .loginProcessingUrl("/login/authenticate")
        .failureUrl("/login?error=bad_credentials")
        .and()
        .logout()
        .logoutUrl("/signout")
        .deleteCookies("JSESSIONID")
        .and()
        .authorizeRequests()
        .antMatchers("/admin/**").hasRole("ADMIN")
        .antMatchers("/**").permitAll()
        .and()
        .csrf();
    }
}

用户详情服务

@Service("myUserDetailsService")
public class MyUserDetailsService implements UserDetailsService
{
    public static final Logger log = Logger.getLogger(MyUserDetailsService.class);

    public MyUserDetailsService() {
    }

    @Autowired
    private UserDao userDao;

    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        final User user = getSystemUser(userName);
        final List<GrantedAuthority> authorities = getUserAuthorities(user);
        return buildUserForAuthentication(user, authorities);
    }

    private User buildUserForAuthentication(User user, List<GrantedAuthority> authorities) {
        //...
    }

    private User getSystemUser(String alias) {
        //...
    }

    private List<GrantedAuthority> getUserAuthorities(User user) {
        //...
        return null;
    }
}

我期望这段代码做的是,当使用user & pass参数到达/login/authenticate时,底层的spring代码调用我的用户服务,但这从未发生过。
我错过了什么?
我使用的是spring-security 3.2.3.RELEASE。

ia2d9nvy

ia2d9nvy1#

您应该在SecurityConfig类中注册您的自定义身份验证,该类具有扩展的WebSecurityConfigureAdapter:

@Autowired
private MyUserDetailsService userDetailsService;

@Override
protected void configure(AuthenticationManagerBuilder auth) 
      throws Exception {
    auth.userDetailsService(this.userDetailsService);
}

对于3.2.3,配置应为

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(this.userDetailsService);
}
63lcw9qa

63lcw9qa2#

@Component
public class JwtUtil {

@Value("${jwt.secret}")
private String secret;

@Value("${jwt.expiration}")
private Long expiration;

Date now = new Date();
Date ExpirationDate = new Date(now.getTime() + expiration * 1000);

public User getUser(final String token) {
    Claims body = Jwts.parser()
        .setSigningKey(secret)
        .parseClaimsJws(token)
        .getBody();

    User u = new User();
    u.setUsername(body.getSubject());
    u.setUserId(Integer.parseInt((String) body.get("userId")));
    Set < Role > roles = new HashSet < > ();
    roles.add(Role.CONSUMER);
    roles.add(Role.SELLER);
    u.setRoles(roles);
    return u;
}

public String generateToken(String username) {
    User u = new User();
    Claims claims = Jwts.claims().setSubject(username);
    claims.put("userId", u.getUserId());
    Set < Role > roles = new HashSet < > ();
    roles.add(Role.CONSUMER);
    roles.add(Role.SELLER);
    claims.put("role", roles);

    return Jwts.builder()
        .setClaims(claims)
        .setIssuedAt(now)
        .setExpiration(ExpirationDate)
        .signWith(SignatureAlgorithm.HS512, secret)
        .compact();

}

public boolean validateToken(final String token) {
    return getClaims(secret, token)
        .getExpiration()
        .after(new Date(System.currentTimeMillis()));
}

public Claims getClaims(String secret, String token) {
    return Jwts.parser()
        .setSigningKey(secret)
        .parseClaimsJws(token)
        .getBody();
}
public Boolean validateToken(String token, UserDetails userDetails) {

    String username = extractUsername(token);

    return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));

}

public String extractUsername(String token) {

    return extractClaim(token, Claims::getSubject);

}

public String extractRole(String token) {

    return (String) extractClaim(token, claims - > claims.get("role"));

}

public Date extractExpiration(String token) {

    return extractClaim(token, Claims::getExpiration);

}

public < T > T extractClaim(String token, Function < Claims, T > claimsResolver) {

    final Claims claims = extractAllClaims(token);

    return claimsResolver.apply(claims);

}

private Claims extractAllClaims(String token) {

    return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();

}

private Boolean isTokenExpired(String token) {

    final Date expiration = extractExpiration(token);

    return expiration.before(new Date());

}
}

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

@Autowired
private JwtUtil jwtTokenUtil;

@Autowired
private UserDetailsService userDetailsService;

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {

    final String authorizationHeader = request.getHeader("Authorization");
    String username = null;
    String jwt = null;

    if (authorizationHeader != null && authorizationHeader.startsWith("JWT ")) {

        jwt = authorizationHeader.substring(7);
        username = jwtTokenUtil.extractUsername(jwt);

    }

    if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

        UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);

        if (jwtTokenUtil.validateToken(jwt, userDetails)) {

            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(

                userDetails, null, userDetails.getAuthorities());

            usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

            SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);

        }

    }

    chain.doFilter(request, response);

}

}

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ApiSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private ApiAuthenticationEntryPoint jwtAuthenticationEntryPoint;

@Autowired
private JwtAuthenticationFilter jwtAuthorizationFilter;

@Autowired
private UserAuthService jwtUserDetailsService;


@Bean
public PasswordEncoder passwordEncoder() {

    return new BCryptPasswordEncoder();

}

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

    auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());

}

@Override
public void configure(WebSecurity web) throws Exception {

}

@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(this.jwtUserDetailsService);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
        .authorizeRequests()
        .antMatchers(HttpMethod.POST, "/authenticate").permitAll()
        .antMatchers("/api/public/**").permitAll()
        .antMatchers("/api/auth/consumer/**").hasRole("CONSUMER")
        .antMatchers("/api/auth/seller/**").hasRole("SELLER")
        .anyRequest().authenticated()
        .and()
        .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
        .and()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    http.addFilterBefore(jwtAuthorizationFilter, UsernamePasswordAuthenticationFilter.class);

}

@Bean
public RegistrationBean jwtAuthFilterRegister(JwtAuthenticationFilter filter) {
    FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
    registrationBean.setEnabled(false);
    return registrationBean;
}

@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}

}

@Component
public class ApiAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
        AuthenticationException authException) throws IOException, ServletException {

    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}

@Service
public class AuthService {

@Autowired
private UserRepo userRepository;

@Autowired
private JwtUtil jwtutil;

public String authenticate(String username, String password) throws AuthenticationException {
    Optional < User > user = userRepository.findByUsername(username);
    if (user == null) {
        throw new AuthenticationException("Invalid username or password");
    }
    return jwtutil.generateToken(username);
}


}

@Service
public class ProductService {

@Autowired
private ProductRepo productRepository;

public List < Product > searchProducts(String keyword) {
    return productRepository.findByProductNameContainingIgnoreCaseOrCategoryCategoryNameContainingIgnoreCase(keyword, keyword);
}

}

@RestController
@RequestMapping("/api/public")
public class PublicController {

@Autowired
private ProductService productService;

@Autowired
private AuthService authService;

@GetMapping("/product/search")
public List < Product > searchProducts(@RequestParam("keyword") String keyword) {
    return productService.searchProducts(keyword);
}

@PostMapping("/login")
public ResponseEntity < String > login(@RequestBody User credentials) {
    try {
        String token = null;
        try {
            token = authService.authenticate(credentials.getUsername(), credentials.getPassword());
        } catch (javax.naming.AuthenticationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return ResponseEntity.ok(token);
    } catch (AuthenticationException e) {
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
    }
}

}

相关问题