Java Spring与JWT的多个@Autowired MongoRepository用法

时间:2019-03-19 02:04:06

标签: java spring mongodb spring-boot spring-security

JWTAuthenticationFilter.java中的successAuthentication函数提供了nullpointerexception。您知道为什么这会成为问题吗?使用相同的bean自动装配是否有问题?

这是我当前的项目结构:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/textView3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Title asdf asdf asdg asgasdg asdfg"
        android:textAppearance="?android:textAppearanceLarge"
        app:layout_constraintEnd_toStartOf="@+id/text"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:layout_editor_absoluteY="66dp" />

    <TextView
        android:id="@+id/text"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="2015"
        android:textAppearance="?android:textAppearanceLarge"
        app:layout_constraintBottom_toBottomOf="@+id/textView3"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/textView3"
        app:layout_constraintTop_toTopOf="@+id/textView3" />

</android.support.constraint.ConstraintLayout>

Application.java

-com
  -register
    -RegisterController.java
  -security
    -JWTAuthenticationFilter.java
    -JWTAuthorizationFilter.java
    -SecurityConstants.java
    -WebSecurity.java
  -user
    -User.java
    -UserRepository.java
    -UserService.java
  -Application.java

UserRepository.java

@Configuration
@SpringBootApplication
public class Application {
  @Bean
  public BCryptPasswordEncoder bCryptPasswordEncoder() {
      return new BCryptPasswordEncoder();
  }

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

UserService.java

@Repository
public interface UserRepository extends MongoRepository<User, String> {
  User findByUsername(String name);
  User findByEmail(String Email);
  User findBy_id(ObjectId id);
}

User.java

@Service
public class UserService implements UserDetailsService {
  @Autowired
  private UserRepository userRepository;

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = this.userRepository.findByUsername(username);
    if(user == null)
        return null;
    List<SimpleGrantedAuthority> authorities = Arrays.asList(new SimpleGrantedAuthority("user"));
    return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);
  }

  public User getUserByUsername(String username) {
    return this.userRepository.findByUsername(username);
  }

  public User getUserBy_id(ObjectId _id) {
    return userRepository.findBy_id(_id);
  }

  public void saveUser(User newUser){
    userRepository.save(newUser);
  }
}

JWTAuthenticationFilter.java

@Document
public final class User {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private ObjectId _id;
  private String email;
  private String username;
  private String password;
  private AccountProperties accountProperties;
  private Address address;
  private List<Pet> pets = new ArrayList<>();
  private String phoneNumber;

  public User() {}

  public User(@JsonProperty("email") String email, @JsonProperty("username") String username,
            @JsonProperty("password") String password) {
    this.email = email;
    this.username = username;
    this.password = password;
  }

  public String get_id() { return _id.toHexString();}

  getters and setters() ...
}

JWTAuthorizationFilter.java

public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

  @Autowired
  private UserRepository userRepo;
  private AuthenticationManager authenticationManager;

  JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
    this.authenticationManager = authenticationManager;
  }

  @Override
  public Authentication attemptAuthentication(HttpServletRequest req,
                                            HttpServletResponse res) throws AuthenticationException {
    try {
        User creds = new ObjectMapper()
                .readValue(req.getInputStream(), User.class);

        return authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(
                        creds.getUsername(),
                        creds.getPassword(),
                        new ArrayList<>())
        );
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
  }

  @Override
  protected void successfulAuthentication(HttpServletRequest req,
                                        HttpServletResponse res,
                                        FilterChain chain,
                                        Authentication auth) throws IOException, ServletException {

    String username = ((org.springframework.security.core.userdetails.User) auth.getPrincipal()).getUsername();

    String token = JWT.create()
            .withSubject(username)
            .withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
            .sign(HMAC512(SECRET.getBytes()));
    res.addHeader(HEADER_STRING, TOKEN_PREFIX + token);
    User u = uRepo.findByUsername("admin");
    res.getWriter().write(
            "{\"" + SecurityConstants.HEADER_STRING + "\":\"" + SecurityConstants.TOKEN_PREFIX+token + "\"," +
            "\"" + "ObjectID" + "\":\"" + u.get_id() + "\"}"
    );
  }
}

WebSecurity.java

public class JWTAuthorizationFilter extends BasicAuthenticationFilter {

  public JWTAuthorizationFilter(AuthenticationManager authManager) {
    super(authManager);
  }

  @Override
  protected void doFilterInternal(HttpServletRequest req,
                                HttpServletResponse res,
                                FilterChain chain) throws IOException, ServletException {
    String header = req.getHeader(HEADER_STRING);

    if (header == null || !header.startsWith(TOKEN_PREFIX)) {
        chain.doFilter(req, res);
        return;
    }

    UsernamePasswordAuthenticationToken authentication = getAuthentication(req);
 SecurityContextHolder.getContext().setAuthentication(authentication);
    chain.doFilter(req, res);
  }

  private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
    String token = request.getHeader(HEADER_STRING);
    if (token != null) {
        // parse the token.
        String user = JWT.require(Algorithm.HMAC512(SECRET.getBytes()))
                .build()
                .verify(token.replace(TOKEN_PREFIX, ""))
                .getSubject();

        if (user != null) {
            return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
        }
        return null;
    }
    return null;
  }
}

SecurityConstants.java

@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
  @Autowired
  private UserService userDetailsService;
  @Autowired
  private BCryptPasswordEncoder bCryptPasswordEncoder;

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.cors().and().csrf().disable().authorizeRequests()
            .antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
            .anyRequest().authenticated()
            .and()
            .addFilter(new JWTAuthenticationFilter(authenticationManager()))
            .addFilter(new JWTAuthorizationFilter(authenticationManager()))
            // this disables session creation on Spring Security
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS );
  }

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

  @Bean
  CorsConfigurationSource corsConfigurationSource() {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
    return source;
  }
}

RegisterController.java

public class SecurityConstants {
  public static final String SECRET = "SecretKeyToGenJWTs";
  public static final long EXPIRATION_TIME = 864_000_000; // 10 days
  public static final String TOKEN_PREFIX = "Bearer ";
  public static final String HEADER_STRING = "Authorization";
  public static final String SIGN_UP_URL = "/users/sign-up";
}

3 个答案:

答案 0 :(得分:0)

不确定这是否是您问题的根本原因,但是我从未在主应用程序中看到@Configuration。我会尝试将其移至单独的配置类,看看是否有帮助

答案 1 :(得分:0)

问题在于您没有将JWTAuthenticationFilter定义为Bean,因此spring不会在其中注入依赖项。

您可以手动将豆放入过滤器中。来自GenericFilterBean javadoc:

  

此通用过滤器基类与Spring org.springframework.context.ApplicationContext概念无关。过滤器通常不加载自己的上下文,而是从Spring根应用程序上下文访问服务Bean,可通过过滤器的ServletContext访问它(请参阅org.springframework.web.context.support.WebApplicationContextUtils)。

或者您可以将其制成bean。但是,如果您使用的是Spring Boot,请考虑:

  

容器不了解Spring Security内部的所有过滤器这一事实很重要,尤其是在Spring Boot应用程序中,默认情况下,所有Filter类型的@Beans都会自动向容器注册。因此,如果要向安全链中添加自定义过滤器,则无需使其成为@Bean或将其包装在明确禁用容器注册的FilterRegistrationBean中。

答案 2 :(得分:0)

用@Component注释JWTAuthenticationFilter或在配置文件中添加@Bean。好像没有创建对象