Skip to content

Commit

Permalink
自定义认证提供者
Browse files Browse the repository at this point in the history
  • Loading branch information
codesverve committed May 5, 2020
1 parent 711ad33 commit 0b9ea06
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 56 deletions.
21 changes: 21 additions & 0 deletions src/main/java/com/uetty/sample/springboot/entity/Role.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.uetty.sample.springboot.entity;

import org.springframework.security.core.GrantedAuthority;

public class Role implements GrantedAuthority {

String name;

public String getName() {
return name;
}

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

@Override
public String getAuthority() {
return getName();
}
}
42 changes: 41 additions & 1 deletion src/main/java/com/uetty/sample/springboot/entity/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.uetty.sample.springboot.enums.UserStatusEnum;
import com.uetty.sample.springboot.enums.UserSysRoleEnum;
import org.springframework.security.core.CredentialsContainer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

public class User {
public class User implements UserDetails, CredentialsContainer {

private String id;
private String username;
Expand All @@ -21,6 +27,8 @@ public class User {
private Date createTime;
private Date updateTime;

List<Role> roleList = new ArrayList<>();

public String getId () {
return this.id;
}
Expand All @@ -30,6 +38,27 @@ public void setId (String id) {
public String getUsername () {
return this.username;
}

@Override
public boolean isAccountNonExpired() {
return true;
}

@Override
public boolean isAccountNonLocked() {
return true;
}

@Override
public boolean isCredentialsNonExpired() {
return true;
}

@Override
public boolean isEnabled() {
return true;
}

public void setUsername (String username) {
this.username = username;
}
Expand All @@ -39,6 +68,12 @@ public String getDisplayName () {
public void setDisplayName (String displayName) {
this.displayName = displayName;
}

@Override
public Collection<Role> getAuthorities() {
return roleList;
}

@JsonIgnore
public String getPassword () {
return this.password;
Expand Down Expand Up @@ -94,4 +129,9 @@ public Date getUpdateTime () {
public void setUpdateTime (Date updateTime) {
this.updateTime = updateTime;
}

@Override
public void eraseCredentials() {
this.password = null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.uetty.sample.springboot.security;

import com.uetty.sample.springboot.dao.UserDao;
import com.uetty.sample.springboot.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Objects;

@Component
public class AuthenticationProviderImpl extends AbstractUserDetailsAuthenticationProvider {

// 限制登录频率
private static final int MAX_FAILED_TIMES = 5;
private static final long FAILED_INTERVAL = 120_000L;

@Autowired
UserDao userDao;

@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
// 校验密码逻辑
String password = authentication.getCredentials().toString();
User user = (User) userDetails;
Integer loginFailedTimes = user.getLoginFailedTimes();
loginFailedTimes = loginFailedTimes == null ? 0 : loginFailedTimes;
long lastLoginTime = user.getLastLoginTime() != null ? user.getLastLoginTime().getTime() : 0L;
Date date = new Date();
// 限制登录失败频率
if (loginFailedTimes >= MAX_FAILED_TIMES
&& date.getTime() - lastLoginTime < FAILED_INTERVAL) {
throw new BadCredentialsException("high login frequency"); // 登录频率过高
}

boolean passwordValid = Objects.equals(password, user.getPassword());
// 更新登录成功和失败信息
user.setLoginFailedTimes(passwordValid ? 0 : loginFailedTimes + 1);
user.setLastLoginTime(date);
user.setUpdateTime(date);
userDao.update(user);
if (!passwordValid) {
throw new BadCredentialsException("login failed");
}
}

@Override
protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
try {
User user = userDao.getByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("username[" + username + "] not found");
}
return user;
} catch (UsernameNotFoundException ne) {
throw ne;
} catch (Exception e) {
throw new InternalAuthenticationServiceException(e.getMessage(), e);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,10 @@
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;


@EnableWebSecurity
Expand All @@ -22,13 +16,6 @@ public class SecurityConfigure extends WebSecurityConfigurerAdapter {

@Configurable
static class SecurityBeanConfigure {
/**
* 这里为security指定一个加密方式(这个加密目的仅是内存安全,数据库里最好还是要单独进行md5加密)
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}

@Value("${server.apiUrlPrefix}/login")
Expand All @@ -39,7 +26,7 @@ public PasswordEncoder passwordEncoder() {
private String logoutPath;

@Autowired
UserDetailsService userDetailsService;
AuthenticationProviderImpl authenticationProvider;

@Override
protected void configure(HttpSecurity http) throws Exception {
Expand Down Expand Up @@ -73,7 +60,7 @@ protected void configure(HttpSecurity http) throws Exception {

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 设置自定义获取用户信息的业务类
auth.userDetailsService(userDetailsService);
// 设置自定义AuthenticationProvider
auth.authenticationProvider(authenticationProvider);
}
}

This file was deleted.

0 comments on commit 0b9ea06

Please sign in to comment.