首页 > 解决方案 > 当我尝试将 angularJs 应用程序连接到 Spring Boot 时出现 401

问题描述

我正在尝试使用 AngularJS 和 Spring Boot 制作应用程序。我浏览了很多教程,我复制了这段代码,但出了点问题。

我不熟悉这些技术,我也可能会错过一些东西。我不知道错误可能出在哪里,所以我将链接到代码所在的github。

https://github.com/BitRuby/YouLoveLife/tree/Stage1

我还添加了可能有错误的类:

过滤器类:

public class JWTFilter extends GenericFilterBean {
private static final String AUTHORIZATION_HEADER = "Authorization";
private static final String AUTHORITIES_KEY = "roles";

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain)
        throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) req;
    String authHeader = request.getHeader(AUTHORIZATION_HEADER);
    if (authHeader == null || !authHeader.startsWith("Bearer ")) {
        ((HttpServletResponse) res).sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid Authorization header.");
    } else {
        try {
            String token = authHeader.substring(7);
            Claims claims = Jwts.parser().setSigningKey("secretkey").parseClaimsJws(token).getBody();
            request.setAttribute("claims", claims);
            SecurityContextHolder.getContext().setAuthentication(getAuthentication(claims));
            filterChain.doFilter(req, res);
        } catch (SignatureException e) {
            ((HttpServletResponse) res).sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid token");
        }

    }
}

/**
 * Method for creating Authentication for Spring Security Context Holder
 * from JWT claims
 *
 * @param claims
 * @return
 */
public Authentication getAuthentication(Claims claims) {
    List<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();
    List<String> roles = (List<String>) claims.get(AUTHORITIES_KEY);
    for (String role : roles) {
        authorities.add(new SimpleGrantedAuthority(role));
    }
    User principal = new User(claims.getSubject(), "", authorities);
    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
            principal, "", authorities);
    return usernamePasswordAuthenticationToken;
}
}

网页配置:

@Configuration
@Configurable
@Order(99)
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

// This method is for overriding some configuration of the WebSecurity
// If you want to ignore some request or request patterns then you can
// specify that inside this method
@Override
public void configure(WebSecurity web) throws Exception {

    web.ignoring()
            // ignoring the "/", "/index.html", "/app/**", "/register",
            // "/favicon.ico"
            .antMatchers("/", "/index.html", "/app/**", "/register", "/authenticate", "/favicon.ico");
}

// This method is used for override HttpSecurity of the web Application.
// We can specify our authorization criteria inside this method.
@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            // starts authorizing configurations
            .authorizeRequests()
            // authenticate all remaining URLS
            .anyRequest().fullyAuthenticated().and()
            // adding JWT filter
            .addFilterBefore(new JWTFilter(), UsernamePasswordAuthenticationFilter.class)
            // enabling the basic authentication
            .httpBasic().and()
            // configuring the session as state less. Which means there is
            // no session in the server
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
            // disabling the CSRF - Cross Site Request Forgery
            .csrf().disable();
}

}

用户应用程序休息:

@RestController
@RequestMapping(value = "/api")
public class AppUserRestController {
@Autowired
private AppUserRepository appUserRepository;

/**
 * Web service for getting all the appUsers in the application.
 *
 * @return list of all AppUser
 */
@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value = "/users", method = RequestMethod.GET)
public List<AppUser> users() {
    return appUserRepository.findAll();
}

/**
 * Web service for getting a user by his ID
 *
 * @param id
 *            appUser ID
 * @return appUser
 */
@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value = "/users/{id}", method = RequestMethod.GET)
public ResponseEntity<AppUser> userById(@PathVariable Long id) {
    AppUser appUser = appUserRepository.getOne(id);
    if (appUser == null) {
        return new ResponseEntity<AppUser>(HttpStatus.NO_CONTENT);
    } else {
        return new ResponseEntity<AppUser>(appUser, HttpStatus.OK);
    }
}

/**
 * Method for deleting a user by his ID
 *
 * @param id
 * @return
 */
@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value = "/users/{id}", method = RequestMethod.DELETE)
public ResponseEntity<AppUser> deleteUser(@PathVariable Long id) {
    AppUser appUser = appUserRepository.getOne(id);
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    String loggedUsername = auth.getName();
    if (appUser == null) {
        return new ResponseEntity<AppUser>(HttpStatus.NO_CONTENT);
    } else if (appUser.getUsername().equalsIgnoreCase(loggedUsername)) {
        throw new RuntimeException("You cannot delete your account");
    } else {
        appUserRepository.delete(appUser);
        return new ResponseEntity<AppUser>(appUser, HttpStatus.OK);
    }

}

/**
 * Method for adding a appUser
 *
 * @param appUser
 * @return
 */
@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value = "/users", method = RequestMethod.POST)
public ResponseEntity<AppUser> createUser(@RequestBody AppUser appUser) {
    if (appUserRepository.findOneByUsername(appUser.getUsername()) != null) {
        throw new RuntimeException("Username already exist");
    }
    return new ResponseEntity<AppUser>(appUserRepository.save(appUser), HttpStatus.CREATED);
}

/**
 * Method for editing an user details
 *
 * @param appUser
 * @return modified appUser
 */
@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value = "/users", method = RequestMethod.PUT)
public AppUser updateUser(@RequestBody AppUser appUser) {
    if (appUserRepository.findOneByUsername(appUser.getUsername()) != null
            && appUserRepository.findOneByUsername(appUser.getUsername()).getId() != appUser.getId()) {
        throw new RuntimeException("Username already exist");
    }
    return appUserRepository.save(appUser);
}

}

像这样的东西:

@RestController
public class HomeRestController {
@Autowired
private AppUserRepository appUserRepository;

/**
 * This method is used for user registration. Note: user registration is not
 * require any authentication.
 *
 * @param appUser
 * @return
 */
@RequestMapping(value = "/register", method = RequestMethod.POST)
public ResponseEntity<AppUser> createUser(@RequestBody AppUser appUser) {
    if (appUserRepository.findOneByUsername(appUser.getUsername()) != null) {
        throw new RuntimeException("Username already exist");
    }
    List<String> roles = new ArrayList<>();
    roles.add("USER");
    appUser.setRoles(roles);
    return new ResponseEntity<AppUser>(appUserRepository.save(appUser), HttpStatus.CREATED);
}

/**
 * This method will return the logged user.
 *
 * @param principal
 * @return Principal java security principal object
 */
@RequestMapping("/user")
public AppUser user(Principal principal) {
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    String loggedUsername = auth.getName();
    return appUserRepository.findOneByUsername(loggedUsername);
}

/**
 * @param username
 * @param password
 * @param response
 * @return JSON contains token and user after success authentication.
 * @throws IOException
 */
@RequestMapping(value = "/authenticate", method = RequestMethod.POST)
public ResponseEntity<Map<String, Object>> login(@RequestParam String username, @RequestParam String password,
                                                 HttpServletResponse response) throws IOException {
    String token = null;
    AppUser appUser = appUserRepository.findOneByUsername(username);
    Map<String, Object> tokenMap = new HashMap<String, Object>();
    if (appUser != null && appUser.getPassword().equals(password)) {
        token = Jwts.builder().setSubject(username).claim("roles", appUser.getRoles()).setIssuedAt(new Date())
                .signWith(SignatureAlgorithm.HS256, "secretkey").compact();
        tokenMap.put("token", token);
        tokenMap.put("user", appUser);
        return new ResponseEntity<Map<String, Object>>(tokenMap, HttpStatus.OK);
    } else {
        tokenMap.put("token", null);
        return new ResponseEntity<Map<String, Object>>(tokenMap, HttpStatus.UNAUTHORIZED);
    }

}
}

我还附上了前端出现的错误:

屏幕

标签: javaangularjsspringspring-boot

解决方案


推荐阅读