1
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Resource(name = "userService")
private UserDetailsService userDetailsService;
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth, DataSource dataSource) throws Exception {
/*auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("select login as principal, mot_de_passe as credentials, flag_compte_actif as enabled from utilisateur where login = ?")
.authoritiesByUsernameQuery("SELECT utilisateur.login as principal, profil.designation as role FROM utilisateur INNER JOIN user_profil ON utilisateur.id_user = user_profil.iduserpk INNER JOIN profil ON user_profil.idprofilpk = profil.id_profil WHERE utilisateur.login = ? ")
.rolePrefix("ROLE_");
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());*/
auth.inMemoryAuthentication()
.withUser("admin")
.password("password")
.roles("Administrateur");
}
@Bean
public JwtAuthenticationFilter authenticationTokenFilterBean() throws Exception {
return new JwtAuthenticationFilter();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println("Akal configure method begin");
//http.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);
http.cors().and()
.csrf().disable().
authorizeRequests()
.antMatchers("/token/generate").permitAll()
.anyRequest().authenticated()
.and().formLogin().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
System.out.println("Akal configure method");
http
.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
}
// @Bean
// public BCryptPasswordEncoder passwordEncoder(){
// return new BCryptPasswordEncoder();
// }
@Bean
public static NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
}
2
@RestController
@CrossOrigin("*")
public class AuthenticationController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private UtilisateurRepository userRepo;
@PostMapping(value = "/token/generate")
public ResponseEntity<?> register(@RequestBody LoginUser loginUser) throws AuthenticationException {
System.out.println("We're in man!");
final Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginUser.getUsername(),
loginUser.getPassword()
)
);
System.out.println("(Username, Password): (" + loginUser.getUsername() + ", " + loginUser.getPassword() + ")");
SecurityContextHolder.getContext().setAuthentication(authentication);
final Utilisateur user = userRepo.findByLogin(loginUser.getUsername());
final String token = jwtTokenUtil.generateToken(user);
System.out.println("Token Controller Access=> Token Generated: " + token);
return ResponseEntity.ok(new AuthToken(token));
}
}
3
public class AuthToken {
private String token;
public AuthToken(){
}
public AuthToken(String token){
this.token = token;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
4
public class CorsFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
System.out.println("Filtering on...........................................................");
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
//response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Authorization, Origin, Accept, Access-Control-Request-Method, Access-Control-Request-Headers");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
5
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}
6
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
String header = req.getHeader("Authorization");
String username = null;
String authToken = null;
if (header != null && header.startsWith("Bearer ")) {
authToken = header.replace("Bearer ","");
try {
username = jwtTokenUtil.getUsernameFromToken(authToken);
} catch (IllegalArgumentException e) {
logger.error("an error occured during getting username from token", e);
} catch (ExpiredJwtException e) {
logger.warn("the token is expired and not valid anymore", e);
} catch(SignatureException e){
logger.error("Authentication Failed. Username or Password not valid.");
}
} else {
logger.warn("couldn't find bearer string, will ignore the header");
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN")));
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(req));
logger.info("authenticated user " + username + ", setting security context");
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
chain.doFilter(req, res);
}
}
7
@Component
public class JwtTokenUtil implements Serializable {
static final long EXPIRATIONTIME = 864_000_000; // 10 days
static final String SECRET = "secret";
static final String TOKEN_PREFIX = "Bearer";
static final String HEADER_STRING = "Authorization";
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
public Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token)
.getBody();
}
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
public String generateToken(Utilisateur user) {
return doGenerateToken(user.getLogin());
}
private String doGenerateToken(String subject) {
Claims claims = Jwts.claims().setSubject(subject);
claims.put("scopes", Arrays.asList(new SimpleGrantedAuthority("ROLE_Administrateur")));
return Jwts.builder()
.setClaims(claims)
.setIssuer("http://devglan.com")
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME))
.signWith(SignatureAlgorithm.HS256, SECRET)
.compact();
}
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = getUsernameFromToken(token);
return (
username.equals(userDetails.getUsername())
&& !isTokenExpired(token));
}
}
8
public class LoginUser {
private String username;
private String password;
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;
}
}
我只发布了这两个类,因为老实说我有8个配置类,所以阅读起来会很痛苦!而且它也是自定义的JWT代码,但是如果有必要将其全部发布,请告诉我。
除此之外,我只是无法确定问题所在! Spring控制台不会显示任何错误,当我尝试向Postman请求时,结果如下: result
当我从浏览器中运行请求时,它没有说401,它只是说错误的凭据,即使它们是正确的,我也尝试了数十个用户以确保
谢谢!
更新:我发布了其余的类,因为问题可能不仅与这2个有关
答案 0 :(得分:0)
您没有在PasswordEncoder
方法中使用globalUserDetails()
。 Spring Security默认情况下采用编码密码。您的代码应类似于。
@Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().passwordEncoder(passwordEncoder)
.withUser("admin")
.password("password")
.roles("Admin");
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
您正在使用不需要dataSource
,因为您正在使用inMemoryAuthenticatin()
。
答案 1 :(得分:0)
在Spring Security 5中,如果您使用BaseString
,则将无法使用auth.inMemoryAuthentication()
或BCryptPasswordEncoder
。您必须使用自己的StandardPasswordEncoder
才能获得用户名和密码。或者,如果您需要测试代码,只需在UserDetailsService
方法中返回NoOpPasswordEncoder.getInstance()
SecurityConfig.class
passwordEncoder()
AccountService.class
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AccountService accountService; //your own implementation of UserDetailsService
....
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.eraseCredentials(true)
.userDetailsService(accountService)
.passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
....
}
Account.class
@Service
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public class AccountService implements UserDetailsService {
@Autowired
private AccountRepository accountRepository; //Your database repository
@Autowired
private PasswordEncoder passwordEncoder;
@PostConstruct
protected void initialize() {
save(new Account("user", "demo", "ROLE_USER"));
save(new Account("admin", "admin", "ROLE_ADMIN"));
}
@Transactional
public Account save(Account account) {
account.setPassword(passwordEncoder.encode(account.getPassword()));
accountRepository.save(account);
return account;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Account account = accountRepository.findOneByEmail(username);
if(account == null) {
throw new UsernameNotFoundException("user not found");
}
return createUser(account);
}
public void signin(Account account) {
SecurityContextHolder.getContext().setAuthentication(authenticate(account));
}
private Authentication authenticate(Account account) {
return new UsernamePasswordAuthenticationToken(createUser(account), null, Collections.singleton(createAuthority(account)));
}
private User createUser(Account account) {
return new User(account.getEmail(), account.getPassword(), Collections.singleton(createAuthority(account)));
}
private GrantedAuthority createAuthority(Account account) {
return new SimpleGrantedAuthority(account.getRole());
}
}