فهرست منبع

登陆失败计数以及账号状态判断

suxiaoyang 6 سال پیش
والد
کامیت
148e70bddc

+ 1 - 1
gateway/ag-basic/src/main/resources/application.yml

@ -11,7 +11,7 @@ zuul:
      serviceId: svr-iot
    svr-base:
      path: /base/**
      serviceId: svr-base-sxy
      serviceId: svr-base
    demo:
      path: /baidu/**
      url: https://www.baidu.com

+ 2 - 0
server/svr-authentication/src/main/java/com/yihu/jw/security/config/WlyyWebSecurityConfigurerAdapter.java

@ -31,6 +31,7 @@ public class WlyyWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapt
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/oauth/**");
        web.ignoring().antMatchers("/health");
    }
    @Override
@ -63,6 +64,7 @@ public class WlyyWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapt
        reflectionSaltSource.setUserPropertyToUse("salt");
        authenticationProvider.setSaltSource(reflectionSaltSource);
        authenticationProvider.setSaltSource(reflectionSaltSource);
        authenticationProvider.setHideUserNotFoundExceptions(false);
        return authenticationProvider;
    }

+ 4 - 0
server/svr-authentication/src/main/java/com/yihu/jw/security/core/userdetails/SaltUser.java

@ -31,6 +31,10 @@ public class SaltUser implements UserDetails, CredentialsContainer {
        this(username, password, salt, true, true, true, true, authorities);
    }
    public SaltUser(String username, String password, String salt, boolean enabled, boolean locked, Collection<? extends GrantedAuthority> authorities) {
        this(username, password, salt, enabled, true, true, !locked, authorities);
    }
    public SaltUser(String username, String password, String salt, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
        if(username != null && !"".equals(username) && password != null) {
            this.username = username;

+ 36 - 10
server/svr-authentication/src/main/java/com/yihu/jw/security/core/userdetails/jdbc/WlyyUserDetailsService.java

@ -3,6 +3,7 @@ package com.yihu.jw.security.core.userdetails.jdbc;
import com.yihu.jw.security.core.userdetails.SaltUser;
import com.yihu.jw.security.model.WlyyUserDetails;
import com.yihu.jw.security.model.WlyyUserSimple;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.security.core.GrantedAuthority;
@ -10,7 +11,10 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.Collection;
@ -18,12 +22,12 @@ import java.util.Date;
import java.util.List;
/**
 * Service - 用户加载
 * Service - 用户信息
 * Created by progr1mmer on 2018/8/29.
 */
public class WlyyUserDetailsService extends JdbcDaoSupport implements UserDetailsService {
    private static final String DEFAULT_USER_DETAILS_STATEMENT = "SELECT * FROM base_user u WHERE u.username = ? OR u.mobile = ? OR u.idcard = ?";
    private static final String DEFAULT_USER_DETAILS_STATEMENT = "select * from base_user u where u.username = ? or u.mobile = ? or u.idcard = ?";
    public WlyyUserDetailsService(DataSource dataSource) {
        this.setDataSource(dataSource);
@ -42,18 +46,19 @@ public class WlyyUserDetailsService extends JdbcDaoSupport implements UserDetail
        if (users == null || users.size() == 0) {
            throw new UsernameNotFoundException(username);
        }
        return new SaltUser(username, users.get(0).getPassword(), users.get(0).getSalt(), getGrantedAuthorities(username));
    }
    private Collection<? extends GrantedAuthority> getGrantedAuthorities(String username) {
        Collection<GrantedAuthority> authorities = new ArrayList<>(1);
        authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
        return authorities;
        if (users.get(0).isLocked()) {
            Date date = users.get(0).getLockedDate();
            if (new Date().after(DateUtils.addMinutes(date, 5))) {
                this.getJdbcTemplate().update("update base_user u set login_failure_count = 0, u.locked = 0 where u.username = ? or u.mobile = ? or u.idcard = ?", username, username, username);
                users.get(0).setLocked(false);
            }
        }
        return new SaltUser(username, users.get(0).getPassword(), users.get(0).getSalt(), users.get(0).isEnabled(), users.get(0).isLocked(), getGrantedAuthorities(username));
    }
    public WlyyUserSimple authSuccess (String username) throws UsernameNotFoundException {
        //更新登陆时间
        this.getJdbcTemplate().update("update base_user u set u.login_date = ? where u.username = ? or u.mobile = ? or u.idcard = ?", new Date(), username, username, username);
        this.getJdbcTemplate().update("update base_user u set login_failure_count = 0, u.login_date = ? where u.username = ? or u.mobile = ? or u.idcard = ?", new Date(), username, username, username);
        //加载用户简略信息
        List<WlyyUserSimple> users = this.getJdbcTemplate().query(DEFAULT_USER_DETAILS_STATEMENT, new BeanPropertyRowMapper(WlyyUserSimple.class), username, username, username);
        if (users == null || users.size() == 0) {
@ -62,4 +67,25 @@ public class WlyyUserDetailsService extends JdbcDaoSupport implements UserDetail
        return users.get(0);
    }
    public String authFailure () throws UsernameNotFoundException {
        //获取失败次数
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String username = request.getParameter("username");
        Integer loginFailureCount = this.getJdbcTemplate().queryForObject("select login_failure_count from base_user u where u.username = ? or u.mobile = ? or u.idcard = ?", Integer.class, username, username, username);
        loginFailureCount ++;
        if (loginFailureCount == 5) {
            this.getJdbcTemplate().update("update base_user u set u.login_failure_count = 5, locked = 1, u.locked_date = ? where u.username = ? or u.mobile = ? or u.idcard = ?", new Date(), username, username, username);
            return "账号已被锁定,请5分钟后重试!";
        } else {
            this.getJdbcTemplate().update("update base_user u set u.login_failure_count = ? where u.username = ? or u.mobile = ? or u.idcard = ?", loginFailureCount, username, username, username);
            return "密码错误,还可以再试" + (5 - loginFailureCount) + "次!";
        }
    }
    private Collection<? extends GrantedAuthority> getGrantedAuthorities(String username) {
        Collection<GrantedAuthority> authorities = new ArrayList<>(1);
        authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
        return authorities;
    }
}

+ 20 - 6
server/svr-authentication/src/main/java/com/yihu/jw/security/oauth2/provider/endpoint/WlyyLoginEndpoint.java

@ -95,6 +95,10 @@ public class WlyyLoginEndpoint extends AbstractEndpoint {
     */
    @RequestMapping(value = "/oauth/login", method = RequestMethod.POST)
    public ResponseEntity<Oauth2Envelop<WlyyUserSimple>> login(@RequestParam Map<String, String> parameters, HttpSession httpSession) throws Exception {
        String username = parameters.get("username");
        if (StringUtils.isEmpty(username)) {
            throw new InvalidRequestException("username");
        }
        String client_id = parameters.get("client_id");
        if (StringUtils.isEmpty(client_id)) {
            throw new InvalidRequestException("client_id");
@ -353,16 +357,13 @@ public class WlyyLoginEndpoint extends AbstractEndpoint {
   @ExceptionHandler(Exception.class)
    public ResponseEntity<Oauth2Envelop> handleException(Exception e) throws Exception {
        LOG.info(e.getMessage(), e);
        LOG.debug(e.getMessage(), e);
        if (e instanceof UsernameNotFoundException) {
            return handleOAuth2Exception(new Oauth2Envelop("用户未注册!", HttpStatus.UNAUTHORIZED.value()), e);
            return handleOAuth2Exception(new Oauth2Envelop("用户不存在!", HttpStatus.UNAUTHORIZED.value()), e);
        } else if (e instanceof NoSuchClientException) {
            return handleOAuth2Exception(new Oauth2Envelop("应用未注册!", HttpStatus.UNAUTHORIZED.value()), e);
        } else if (e instanceof InvalidGrantException) {
            if (e.getMessage().contains("captcha")) {
                return handleOAuth2Exception(new Oauth2Envelop("验证码有误!", HttpStatus.UNAUTHORIZED.value()), e);
            }
            return handleOAuth2Exception(new Oauth2Envelop("密码有误!", HttpStatus.UNAUTHORIZED.value()), e);
            return handleOAuth2Exception(new Oauth2Envelop(invalidGrantMessage((InvalidGrantException)e), HttpStatus.UNAUTHORIZED.value()), e);
        } else if (e instanceof InvalidTokenException) {
            return handleOAuth2Exception(new Oauth2Envelop("Token有误!", HttpStatus.UNAUTHORIZED.value()), e);
        } else if (e instanceof InvalidRequestException) {
@ -375,6 +376,19 @@ public class WlyyLoginEndpoint extends AbstractEndpoint {
        return handleOAuth2Exception(new Oauth2Envelop(e.getMessage(), -1), e);
    }
    private String invalidGrantMessage(InvalidGrantException e) {
        if (e.getMessage().equals("User is disabled")) {
            return "账号不可用!";
        } else if (e.getMessage().equals("User account is locked")) {
            return "账号已被锁定,请稍后重试!";
        } else if (e.getMessage().equals("Bad credentials")) {
            return userDetailsService.authFailure();
        } else if (e.getMessage().equals("Invalid captcha")) {
            return "验证码错误!";
        }
        return e.getMessage();
    }
    private ResponseEntity<Oauth2Envelop> handleOAuth2Exception(Oauth2Envelop authenticationFailed, Exception e) throws IOException {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Cache-Control", "no-store");

+ 5 - 5
server/svr-authentication/src/main/resources/application.yml

@ -18,11 +18,11 @@ spring:
      max-wait: -1 # Maximum amount of time (in milliseconds) a connection allocation should block before throwing an exception when the pool is exhausted. Use a negative value to block indefinitely.
      min-idle: 1 # Target for the minimum number of idle connections to maintain in the pool. This setting only has an effect if it is positive.
logging:
  level:
    org:
      springframework:
        security: DEBUG
#logging:
#  level:
#    org:
#      springframework:
#        security: DEBUG
---
spring:

+ 0 - 57
svr/svr-base/src/main/java/com/yihu/jw/base/config/BaseJpa.java

@ -1,57 +0,0 @@
//package com.yihu.jw.base.config;
//
//
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.Qualifier;
//import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
//import org.springframework.boot.context.properties.ConfigurationProperties;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.context.annotation.Primary;
//import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
//import org.springframework.orm.jpa.JpaTransactionManager;
//import org.springframework.orm.jpa.JpaVendorAdapter;
//import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
//import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
//import org.springframework.transaction.annotation.EnableTransactionManagement;
//
//import javax.persistence.EntityManagerFactory;
//import javax.sql.DataSource;
//
///**
// * Created by chenweida on 2017/4/6.
// */
//@Configuration
//@EnableTransactionManagement
//@EnableJpaRepositories(
//        entityManagerFactoryRef = "baseEntityManagerFactory",
//        transactionManagerRef = "baseTransactionManager",
//        basePackages = {"com.yihu.jw.business"})   //设置Repository所在位置
//public class BaseJpa {
//
//    @Autowired
//    private HibernateProperties hibernateProperties;
//
//    @Bean(name = "baseEntityManagerFactory")
//    @Primary
//    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(DataSource dataSource) {
//
//        LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
//        emfb.setDataSource(dataSource);
//        emfb.setPackagesToScan("com.yihu.jw.base");
//        emfb.setPersistenceUnitName("base");
//        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
//        emfb.setJpaVendorAdapter(vendorAdapter);
//        emfb.setJpaProperties(hibernateProperties.hibProperties());
//
//        return emfb;
//    }
//
//
//    @Bean(name = "baseTransactionManager")
//    @Primary
//    JpaTransactionManager transactionManagerSecondary(
//            @Qualifier("baseEntityManagerFactory") EntityManagerFactory builder) {
//        return new JpaTransactionManager(builder);
//    }
//}

+ 0 - 43
svr/svr-base/src/main/java/com/yihu/jw/base/config/HibernateProperties.java

@ -1,43 +0,0 @@
//package com.yihu.jw.base.config;
//
//import org.hibernate.EmptyInterceptor;
//import org.hibernate.Interceptor;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.cloud.context.config.annotation.RefreshScope;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.stereotype.Component;
//
//import java.util.List;
//import java.util.Properties;
//
///**
// * Created by chenweida on 2017/4/6.
// */
//@Configuration
//@Component
//public class HibernateProperties {
//    @Value("${hibernate.dialect}")
//    private String dialect;
//    @Value("${hibernate.show_sql}")
//    private String show_sql;
////    @Value("${hibernate.ejb.naming_strategy}")
////    private String naming_strategy;
//
//    @Value("${hibernate.physical_naming_strategy}")
//    private String physical_naming_strategy;
//    @Value("${hibernate.implicit_naming_strategy}")
//    private String implicit_naming_strategy;
////    @Autowired
////    private List<Interceptor> interceptors;
//
//    public Properties hibProperties() {
//        Properties properties = new Properties();
//        properties.put("hibernate.dialect", dialect);
//        properties.put("hibernate.show_sql", show_sql);
//        properties.put("hibernate.physical_naming_strategy", physical_naming_strategy);
//        properties.put("hibernate.implicit_naming_strategy", implicit_naming_strategy);
//        //properties.put("hibernate.ejb.interceptor", interceptors.get(0));
//        return properties;
//    }
//}

+ 21 - 14
svr/svr-base/src/main/java/com/yihu/jw/base/config/SwaggerDocs.java

@ -1,5 +1,12 @@
package com.yihu.jw.base.config;
import io.github.swagger2markup.GroupBy;
import io.github.swagger2markup.Language;
import io.github.swagger2markup.Swagger2MarkupConfig;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder;
import io.github.swagger2markup.markup.builder.MarkupLanguage;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
@ -17,19 +24,19 @@ public class SwaggerDocs {
        String prefix = Thread.currentThread().getContextClassLoader().getResource("").getPath();
        Path outputFile = Paths.get(prefix.substring(prefix.lastIndexOf(":") + 1, prefix.indexOf("target") - 1) + "/build/" + group); //文档输出地址
//        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
//                .withMarkupLanguage(MarkupLanguage.ASCIIDOC)
//                .withOutputLanguage(Language.ZH)
//                .withPathsGroupedBy(GroupBy.TAGS)
//                .withGeneratedExamples()
//                .withoutInlineSchema()
//                //.withBasePathPrefix()
//                .build();
//
//        Swagger2MarkupConverter converter = Swagger2MarkupConverter.from(remoteSwaggerFile)
//                .withConfig(config)
//                .build();
//
//        converter.toFile(outputFile);
        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
                .withMarkupLanguage(MarkupLanguage.ASCIIDOC)
                .withOutputLanguage(Language.ZH)
                .withPathsGroupedBy(GroupBy.TAGS)
                .withGeneratedExamples()
                .withoutInlineSchema()
                //.withBasePathPrefix()
                .build();
        Swagger2MarkupConverter converter = Swagger2MarkupConverter.from(remoteSwaggerFile)
                .withConfig(config)
                .build();
        converter.toFile(outputFile);
    }
}

+ 1 - 1
wlyy-parent-pom/pom.xml

@ -375,7 +375,7 @@
                <version>${asciidoctor.maven.plugin.version}</version>
                <configuration>
                    <sourceDirectory>build</sourceDirectory>
                    <outputDirectory>docs/${project.version}</outputDirectory>
                    <outputDirectory>doc/${project.version}</outputDirectory>
                    <headerFooter>true</headerFooter>
                    <doctype>book</doctype>
                    <sourceHighlighter>coderay</sourceHighlighter>