我是Spring Boot Security的新手,并尝试实现基于JWT的身份验证和授权。我已经为弹簧安全性完成了所有必需的设置配置。即使使用了正确的凭据,Spring Security也会出现错误-错误的凭据。 我已经硬编码了用户详细信息,以确保春季安全(无需数据库调用)。
我的代码如下所示,
SpringConfig.java
package com.wocs.rest.controller;
//import com.example.polls.security.CustomUserDetailsService;
//import com.example.polls.security.JwtAuthenticationEntryPoint;
//import com.example.polls.security.JwtAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.wocs.rest.security.CustomUserDetailsService;
import com.wocs.rest.security.JwtAuthenticationEntryPoint;
import com.wocs.rest.security.JwtAuthenticationFilter;
/**
* Created by rajeevkumarsingh on 01/08/17.
*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
securedEnabled = true,
jsr250Enabled = true,
prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@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());
}
@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("/auth/login")
.permitAll()
.anyRequest()
.authenticated();
// Add our custom JWT security filter
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
CustomUserDetailsService.java
package com.wocs.rest.security;
import com.wocs.services.user.iface.UserServiceIface;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* Created by rajeevkumarsingh on 02/08/17.
*/
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserServiceIface userService;
public void setUserService(UserServiceIface userService) {
this.userService = userService;
}
@Override
@Transactional
public UserDetails loadUserByUsername(String loginIDorPhoneOrEmail)
throws UsernameNotFoundException {
// Let people login with either loginID or email or Phone
//User user = new User();
//UserPassword userPassword = new UserPassword();
List<String> permissions = new ArrayList<>();
permissions.add("P1");
permissions.add("P2");
permissions.add("P3");
UserDetails userDetails = UserPrincipal.create(115, loginIDorPhoneOrEmail,"222",true, permissions);
return userDetails;
}
}
JWTAuthenticationEntryPoint.java
package com.wocs.rest.security;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by rajeevkumarsingh on 07/12/17.
*/
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationEntryPoint.class);
@Override
public void commence(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
AuthenticationException e) throws IOException, ServletException {
logger.error("Responding with unauthorized error. Message - {}", e.getMessage());
httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED,
"Sorry, You're not authorized to access this resource.");
}
}
UserPrincipal.java
package com.wocs.rest.security;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public class UserPrincipal implements UserDetails {
private int id;
private String username;
@JsonIgnore
private String password;
private boolean isCredentialNonExpired = false;
private Collection<? extends GrantedAuthority> authorities;
public UserPrincipal(int id, String username, String password, boolean isCredentialNonExpired, Collection<? extends GrantedAuthority> authorities) {
this.id = id;
this.username = username;
this.password = password;
this.authorities = authorities;
this.isCredentialNonExpired = isCredentialNonExpired;
}
public static UserPrincipal create(int userID, String userName, String password,boolean isCredentialNonExpired, List<String> permissions) {
List<GrantedAuthority> authorities = permissions.stream().map(permission ->
new SimpleGrantedAuthority(permission)
).collect(Collectors.toList());
return new UserPrincipal(
userID,
userName,
password,
isCredentialNonExpired,
authorities
);
}
public int getId() {
return id;
}
@Override
public String getUsername() {
return username;
}
@Override
public String getPassword() {
return password;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return isCredentialNonExpired;
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserPrincipal that = (UserPrincipal) o;
return Objects.equals(id, that.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
AuthController.java
@RequestMapping(value = "/login", method = RequestMethod.POST, consumes = "text/plain")
public Map login(@RequestBody String stringRequestBody) throws JsonParseException, JsonMappingException, IOException, ServiceException
{
logger.info("Auth JSON Request:" + stringRequestBody);
Map<String, String> jsonMap = parseJSON(stringRequestBody);
String username = "rahul@gmail.com";
String password = "222";
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(username,password)
);
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = tokenProvider.generateToken(authentication);
User user = userService.getUserByLoginIDOrPhoneOrEmail(username);
Map userDetail = new HashMap<String, Object>();
if (user != null) {
userDetail.put("user", user);
userDetail.put("userType", userService.getUserTypeByUserID(user.getID()));
userDetail.put("permissions", userService.getUserPermissions(user.getID()));
userDetail.put("token", jwt);
}
return userDetail;
}
我试图击中api,但是它把我扔了:
{
"timestamp":"2018-08-08T08:42:14.575+0000",
"status":401,
"error":"Unauthorized",
"message":"Sorry, You're not authorized to access this resource.",
"path":"/auth/login"
}
记录错误-Responding with unauthorized error. Message - Bad credentials
我已经在下面提到了Spring安全性实施的链接 https://www.callicoder.com/spring-boot-spring-security-jwt-mysql-react-app-part-2/
请帮助我。