如何使用JWT身份验证和授权设置spring安全配置?

时间:2018-11-09 09:39:34

标签: spring spring-boot spring-security spring-data-jpa jwt

我正在尝试创建一个身份验证和授权系统,但是出了点问题,但是我无法弄清楚。这些是类:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
    securedEnabled = true,
    jsr250Enabled = true,
    prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
@Qualifier("datasource")
DataSource dataSource;

@Autowired
CustomUserDetailsService customUserDetailsService;

@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;

@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
    return new JwtAuthenticationFilter();
}

@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
    /*authenticationManagerBuilder
            .userDetailsService(customUserDetailsService)
            .passwordEncoder(passwordEncoder());*/
    authenticationManagerBuilder.userDetailsService(customUserDetailsService);
    authenticationManagerBuilder
        .jdbcAuthentication().dataSource(dataSource)
        .usersByUsernameQuery("select username,pass, enabled from users where username=?")
        .authoritiesByUsernameQuery(
            "SELECT u.username, r.name FROM users u" + 
        "INNER JOIN user_roles ur on u.userid = ur.user_id + "
        + "INNER JOIN roles r on ur.role_id=r.id where username=?");
}

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

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .cors()
                .and()
            .csrf()
                .disable()
            .exceptionHandling()
                .authenticationEntryPoint(unauthorizedHandler)
                .and()
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
            .authorizeRequests()
                .antMatchers("/",
                    "/favicon.ico",
                    "/**/*.png",
                    "/**/*.gif",
                    "/**/*.svg",
                    "/**/*.jpg",
                    "/**/*.html",
                    "/**/*.css",
                    "/**/*.js")
                    .permitAll()
                .antMatchers("/api/auth/**")
                    .permitAll()
                .antMatchers("/api/user/checkUsernameAvailability", "/api/user/checkEmailAvailability")
                    .permitAll()
                .antMatchers(HttpMethod.GET, "/api/polls/**", "/api/users/**")
                    .permitAll()
                .anyRequest()
                    .authenticated();

    // Add our custom JWT security filter
    http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);

}
}

型号:

    @Entity
    @Table(name="users")
    public class User implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="userid")
    private Long id;

    @NotNull
    @Size(min=2, message="Lastname should have atleast 2 characters")
    @Column(name="lastname")
    private String lastname;

    @NotNull
    @Size(min=2, message="Name should have atleast 2 characters")
    @Column(name="name")
    private String firstname;

    @NotNull
    @Column(name="email")
    private String email;

    @NotNull
    @Size(min=4, message="Username should have atleast 4 characters")
    @Column(name="username")
    private String username;

    @NotNull
    @Column(name="birthdate")
    private Date birthdate;

    @NotNull
    @Size(min=8, message="Password should have atleast 8 characters")
    @Column(name="pass")
    private String password;

    @Column(name="city")
    private String city;

    @Column(name="state")
    private String state;

    @Column(name = "enabled")
    private Short enabled;

    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinTable(name = "user_roles", joinColumns = {
            @JoinColumn(name = "user_id") }, inverseJoinColumns = {
            @JoinColumn(name = "role_id") })
    private Set<Role> roles;


    public User() {

    }
    public User(String username, String password) {
        super();
        this.username = username;
        this.password = password;
    }


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public Date getBirthdate() {
        return birthdate;
    }

    public void setBirthdate(Date birthdate) {
        this.birthdate = birthdate;
    }

    public Set<Role> getRoles() {
        Set<Role> roles = new HashSet<>();
        roles.add(new Role());
        return roles;
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }
    public Short getEnabled() {
        return enabled;
    }
    public void setEnabled(Short enabled) {
        this.enabled = enabled;
    }

}

    //
    @Entity
    @Table(name = "roles")
    public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column()
    private Long id;

    @Enumerated(EnumType.STRING)
    @NaturalId
    @Column(length = 60)
    private RoleName name;

    public Role() {

    }

    public Role(RoleName name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public RoleName getName() {
        return name;
    }

    public void setName(RoleName name) {
        this.name = name;
    }

}

    public enum  RoleName {
    ROLE_USER,
    ROLE_ADMIN
}

我已经创建了JWTTokenProvider,UserServiceDetailsS​​ervice,UserServiceDetails和JWTAuthenticationEntryPoint。我还在.properties文件中配置了数据库。注册进行得很好,但是创建的用户的登录返回401(未授权)。

@RestController
@RequestMapping("/api/auth")
public class AuthController {

    @Autowired
    AuthenticationManager authenticationManager;

    @Autowired
    UserRepository userRepository;


    @Autowired
    PasswordEncoder passwordEncoder;

    @Autowired
    JwtTokenProvider tokenProvider;

    @PostMapping("/login")
    public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {

        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(
                        loginRequest.getUsernameOrEmail(),
                        loginRequest.getPassword()
                )
        );

        SecurityContextHolder.getContext().setAuthentication(authentication);

        String jwt = tokenProvider.generateToken(authentication);
        return ResponseEntity.ok(new JwtAuthenticationResponse(jwt));
    }

    @PostMapping("/signup")
    public ResponseEntity<?> registerUser(@Valid @RequestBody SignUpRequest signUpRequest) {
        if(userRepository.existsByUsername(signUpRequest.getUsername())) {
            return new ResponseEntity(new ApiResponse(false, "Username is already taken!"),
                    HttpStatus.BAD_REQUEST);
        }

        if(userRepository.existsByEmail(signUpRequest.getEmail())) {
            return new ResponseEntity(new ApiResponse(false, "Email Address already in use!"),
                    HttpStatus.BAD_REQUEST);
        }

        // Creating user's account
//        User user = new User(signUpRequest.getName(), signUpRequest.getUsername(),
//                signUpRequest.getEmail(), signUpRequest.getPassword());

        User user = new User();
        user.setFirstname(signUpRequest.getName());
        user.setLastname("Bla bla");
        user.setUsername(signUpRequest.getUsername());
        user.setEmail(signUpRequest.getEmail());
        user.setPassword(signUpRequest.getPassword());
        user.setBirthdate(Calendar.getInstance().getTime());
        user.setPassword(passwordEncoder.encode(user.getPassword()));
//      Use this code once the roles are in database
//        Role userRole = roleRepository.findByName(RoleName.ROLE_USER)
//                .orElseThrow(() -> new AppException("User Role not set."));
        if(userRepository.numberOfUsers() == 0) {
            Role userRole = new Role(RoleName.ROLE_ADMIN);
            user.setRoles(Collections.singleton(userRole));
        } else {
            Role userRole = new Role(RoleName.ROLE_USER);
            user.setRoles(Collections.singleton(userRole));
        }
        user.setEnabled((short)1);

        User result = userRepository.save(user);

        URI location = ServletUriComponentsBuilder
                .fromCurrentContextPath().path("/api/users/{username}")
                .buildAndExpand(result.getUsername()).toUri();

        return ResponseEntity.created(location).body(new ApiResponse(true, "User registered successfully"));
    }
}

有人可以帮我吗?

编辑

spring.jpa.database = POSTGRESQL
spring.datasource.platform = postgres
spring.jpa.show-sql = true
spring.datasource.driver-class-name = org.postgresql.Driver
# disable driver's feature detection
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false

# without detection you have to set the dialect by hand
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect

# parametri za konekciju (zameniti X sa odgovarajucim parametrima)
spring.jpa.hibernate.ddl-auto = create
spring.datasource.jdbcUrl = jdbc:postgresql://localhost:5432/resttest
spring.datasource.username = postgres
spring.datasource.password = klasikaK1
#
## proxy problem sa bean-ovima
spring.jackson.serialization.fail-on-empty-beans = false


#port
server.port=8085

## App Properties
app.jwtSecret= JWTSuperSecretKey
app.jwtExpirationInMs = 604800000

没有消息,只有代码401(未授权)。我能够创建一个用户,并且密码在数据库中被散列。

0 个答案:

没有答案