我有一个带有/api/users/register和/api/users/loginendpoint的spring boot项目,registerendpoint工作正常,允许我发布以创建新用户(带有验证等),但当我尝试使用正确的详细信息登录时,登录endpoint会给我401(未经授权)响应。
此外,我正在尝试在创建用户时为他们添加新角色,但由于我使用的是JWT,我不确定如何进行此操作,每个在线教程都有不同的实现,我也在努力理解这一点。
如果有人能为我提供一些步骤,我将不胜感激。我知道您需要在生成令牌本身时将角色添加为声明,但我需要在何处实现在创建帐户时分配新角色的实际逻辑。
使用者Java语言
@Entity
@Table(name="user")
public class User{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
@NotBlank(message = "Username is required")
private String username;
@NotBlank(message = "Password is required")
private String password;
@Transient
private String confirmPassword;
private boolean enabled;
@JsonFormat(pattern = "yyyy-mm-dd")
private Date createdAt;
// I want to load all the roles of users + the user itself once requested for
@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 = new HashSet<>();
// no-arg and all arg constructor
// getters & setters
角色Java语言
@Entity
@Table(name="role")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String description;
// constructors
// getters & setters
**我确实为这两个实体提供了存储库/dao类,并提供了按名称查找用户/角色的方法**
用户服务。Java语言
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private BCryptPasswordEncoder passwordEncoder;
@Autowired
private RoleService roleService;
public User saveUser(User user) {
try {
user.setPassword(passwordEncoder.encode(user.getPassword()));
user.setUsername(user.getUsername());
user.setConfirmPassword("");
user.setEnabled(true);
return userRepository.save(user);
} catch(Exception e) {
throw new UsernameAlreadyExistsException("User with username " + user.getUsername() + " already exists!");
}
}
}
角色服务。Java语言
@Service
public class RoleService {
@Autowired
private RoleRepository roleRepository;
public Role findByRoleName(String roleName) {
Role theRole = roleRepository.findByName(roleName);
return theRole;
}
}
UserDetailsServiceImpl。Java语言
@Service
public class UserDetailsServiceImpl 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");
}
return (UserDetails) user;
}
}
这些是我的JWT课程
**JwtAuthenticationFilter。Java语言
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtTokenProvider tokenProvider;
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
try {
String jwt = getJWTFromRequest(httpServletRequest);
if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {
String username = tokenProvider.getUsernameFromJwt(jwt);
User userDetails = (User) userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails, null, Collections.emptyList());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception ex) {
logger.error("Could not set user authentication in security context", ex);
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
private String getJWTFromRequest(HttpServletRequest request) {
// Header Authorization: Bearer token
String bearerToken = request.getHeader("Authorization");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7, bearerToken.length());
}
return null;
}
}
JwtTokenProvider.java
@Component
public class JwtTokenProvider {
// Generate the token
public String generateToken(Authentication authentication) {
User user = (User) authentication.getPrincipal();
Date now = new Date(System.currentTimeMillis());
Date expiryDate = new Date(now.getTime() + 300_000);
String userId = Long.toString(user.getId());
// this is what holds the token
// add roles in claims
Map<String, Object> claims = new HashMap<>();
claims.put("id", (Long.toString(user.getId())));
claims.put("username", user.getUsername());
return Jwts.builder().setSubject(userId).setClaims(claims).setIssuedAt(now).setExpiration(expiryDate)
.signWith(SignatureAlgorithm.HS512, "SECRETSECRETSECRET").compact();
}
// Validate the token
public boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey("SECRETSECRETSECRET").parseClaimsJws(token);
return true;
} catch (SignatureException ex) {
System.out.println("Invalid JWT Signature");
} catch (MalformedJwtException ex) {
System.out.println("Invalid JWT Token");
} catch (ExpiredJwtException ex) {
System.out.println("Expired JWT Token");
} catch (UnsupportedJwtException ex) {
System.out.println("Unsupported JWT token");
} catch (IllegalArgumentException ex) {
System.out.println("JWT claims string is empty");
}
return false;
}
public String getUsernameFromJwt(String token) {
Claims claims = Jwts.parser().setSigningKey("SECRETSECRETSECRET").parseClaimsJws(token).getBody();
return claims.getSubject();
}
}
JwtAuthenticationEntryPoint。Java语言
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
InvalidLoginResponse loginResponse = new InvalidLoginResponse();
// InvalidLoginResponse is a class with username and password fields and a no-arg
constructor initialiting them like this
// this.username = "Invalid Username";
// this.password = "Invalid Password";
String jsonLoginResponse = new Gson().toJson(loginResponse);
httpServletResponse.setContentType("application/json");
httpServletResponse.setStatus(401);
httpServletResponse.getWriter().print("ERROR FROM JwtAuthenticationEntryPoint: " + jsonLoginResponse);
}
}
安全Config.java
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
// Here i am permitting access to all URLs but getting 401 when posting to /login
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().authorizeRequests()
.anyRequest().permitAll();
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
用户控制器。Java语言
@RestController
@RequestMapping("/api/users")
@CrossOrigin
public class UserController {
private UserService userService;
private UserDetailsServiceImpl userDetailsService;
private UserValidator userValidator;
private ErrorValidationService errorValidationService;
private JwtTokenProvider tokenProvider;
private AuthenticationManager authenticationManager;
@Autowired
public UserController(UserService userService, UserDetailsServiceImpl userDetailsService, UserValidator userValidator, ErrorValidationService errorValidationService, JwtTokenProvider tokenProvider, AuthenticationManager authenticationManager) {
this.userService = userService;
this.userDetailsService = userDetailsService;
this.userValidator = userValidator;
this.errorValidationService = errorValidationService;
this.tokenProvider = tokenProvider;
this.authenticationManager = authenticationManager;
}
// I want to allow role based access to these URLs
@GetMapping("/all")
public String welcomeAll() {
return "Anyone can view this!";
}
@GetMapping("/admin")
public String adminPing(){
return "Only Admins Can view This";
}
@GetMapping("/user")
public String userPing(){
return "Any User Can view This";
}
@PostMapping("/register")
public ResponseEntity<?> register(@Valid @RequestBody User user, BindingResult result) {
userValidator.validate(user, result);
ResponseEntity<?> errorMap = errorValidationService.validationService(result);
if(errorMap != null) return errorMap;
User newUser = userService.saveUser(user);
return new ResponseEntity<User>(newUser, HttpStatus.CREATED);
}
@PostMapping("/login")
public ResponseEntity<?> generateToken(@Valid @RequestBody LoginRequest loginRequest, BindingResult result) throws Exception {
System.out.println("Entering /login");
ResponseEntity<?> errorMap = errorValidationService.validationService(result);
if(errorMap != null) return errorMap;
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = "Bearer " + tokenProvider.generateToken(authentication);
return ResponseEntity.ok(new JwtLoginSuccessResponse(true, jwt));
}
}
尝试在postman/api/users/register中注册时
当试图登录邮递员 /api/users/register
当您为所有传入请求添加OncePerRequest estFilter时。因此,当您调用 /api/users/login它将检查JWT令牌,并且无法在标头中找到它,因此它抛出401(未经授权)。要从OncePerRequest estFilter中排除 /api/users/login终端,您需要覆盖应不过滤(HttpServletRequest)
public class LoginFilter extends OncePerRequestFilter {
private List<String> excludeUrlPatterns = new ArrayList<String>();
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException
{
//Business logic
}
@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException
{
// add excludeUrlPatterns on which one to exclude here
}
}
有关更多信息,请访问:OncePerRequestFilter
Using a delegation key The collaborator can now push to the repository using Docker Content Trust. Docker will automatically choose and pick the right key for the targets/release role. Edit the file o
Importing a delegation certificate As a repository owner: Add the delegation key to the repository using the targets/releases path, as this is what Docker searches for when signing an image (first tar
我的数据未发布在postman api中,这会导致以下错误: 单调的节奏。我的主人。com/api/领域:1个职位http://dradiobeats.x10host.com/api/areas401(未授权)核心。js:4002错误HttpErrorResponse 我的app.component.ts 如何解决此错误?
问题内容: 我从Nexus存储库中检出了代码。我更改了帐户密码,并在文件中正确设置了密码。在执行时,我收到错误消息,说明它尝试从该存储库下载文件。 任何想法如何解决此错误?我在Maven 3.04中使用Windows 7 问题答案: 这里的问题是所使用的密码出现错字错误,由于密码中使用了字符/字母,因此很难识别。
Generating a delegation key Make sure you’re using OpenSSL 1.0.2+, otherwise the keys will be signed with SHA1, which Notary will refuse to import (invalid SHA1 signature algorithm): ❯ brew install op
以下是收到的错误消息: “ErrorMessage”:“401未经授权:[{\r\n\”错误“:{\r\n \”代码\“:\”invalidauthenticationToken\“,\r\n\”消息\“:\”访问令牌验证失败。\“,\r\n\”innererror\“:{\r\n \”日期\“:”2020-06-12T11:49:22\“,\r\n\”请求-id\“:”7988BD2E-3274