forked from kidgrow-microservices-platform

zhaoxiaohao
2020-08-10 34fd8233bab7c8a00211644579942086deea722f
添加 token 失效和token 超时的功能
8 files modified
202 ■■■■ changed files
kidgrow-commons/kidgrow-authclient-spring-boot-starter/src/main/java/com/kidgrow/authclient/store/CustomRedisTokenStore.java 12 ●●●● patch | view | raw | blame | history
kidgrow-uaa/kidgrow-uaa-server/src/main/java/com/kidgrow/oauth2/config/AuthorizationServerConfig.java 46 ●●●● patch | view | raw | blame | history
kidgrow-uaa/kidgrow-uaa-server/src/main/java/com/kidgrow/oauth2/config/SecurityConfig.java 27 ●●●●● patch | view | raw | blame | history
kidgrow-uaa/kidgrow-uaa-server/src/main/java/com/kidgrow/oauth2/handler/SingleTokenServices.java 9 ●●●●● patch | view | raw | blame | history
kidgrow-web/kidgrow-web-manager/src/main/resources/static/assets/js/common.js 15 ●●●● patch | view | raw | blame | history
kidgrow-web/kidgrow-web-manager/src/main/resources/static/module/admin.js 17 ●●●● patch | view | raw | blame | history
kidgrow-web/kidgrow-web-manager/src/main/resources/static/module/apiUrl.js 1 ●●●● patch | view | raw | blame | history
kidgrow-web/kidgrow-web-manager/src/main/resources/static/pages/opration/doctor_form.html 75 ●●●●● patch | view | raw | blame | history
kidgrow-commons/kidgrow-authclient-spring-boot-starter/src/main/java/com/kidgrow/authclient/store/CustomRedisTokenStore.java
@@ -291,12 +291,12 @@
            }
            conn.rPush(clientId, serializedAccessToken);
            if (token.getExpiration() != null) {
                int seconds = token.getExpiresIn();
                conn.expire(accessKey, seconds);
                conn.expire(authKey, seconds);
                conn.expire(authToAccessKey, seconds);
                conn.expire(clientId, seconds);
                conn.expire(approvalKey, seconds);
//                int seconds = token.getExpiresIn();
//                conn.expire(accessKey, seconds);
//                conn.expire(authKey, seconds);
//                conn.expire(authToAccessKey, seconds);
//                conn.expire(clientId, seconds);
//                conn.expire(approvalKey, seconds);
            }
            //关闭Token刷新
//            OAuth2RefreshToken refreshToken = token.getRefreshToken();
kidgrow-uaa/kidgrow-uaa-server/src/main/java/com/kidgrow/oauth2/config/AuthorizationServerConfig.java
@@ -3,19 +3,27 @@
import com.kidgrow.oauth2.handler.SingleTokenServices;
import com.kidgrow.oauth2.service.impl.RedisClientDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.code.RandomValueAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
@@ -42,8 +50,9 @@
    /**
     * 注入authenticationManager 来支持 password grant type
     */
    @Autowired
    private AuthenticationManager authenticationManager;
//   @Autowired
//    private AuthenticationManager authenticationManager;
    @Resource
    private UserDetailsService userDetailsService;
@@ -69,6 +78,11 @@
    @Autowired
    private RandomValueAuthorizationCodeServices authorizationCodeServices;
    @Autowired
    private AuthenticationProvider daoAuhthenticationOauthProvider;
    @Autowired
    private SingleTokenServices tokenServices;
    /**
     * 配置身份认证器,配置认证方式,TokenStore,TokenGranter,OAuth2RequestFactory
@@ -88,15 +102,35 @@
        }
        endpoints
                //扩展tokenServices
//                .tokenServices(tokenServices(endpoints))
                .tokenServices(KidgrowTokenServices())
                .authenticationManager(authenticationManager)
                .authenticationManager(new AuthenticationManager(){
                    @Override
                    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
                        String token = (String) authentication.getPrincipal();
                        OAuth2Authentication auth = tokenServices.loadAuthentication(token);
                        if (auth == null) {
                            throw new InvalidTokenException("Invalid token: " + token);
                        }
                        return daoAuhthenticationOauthProvider.authenticate(authentication);
                    }
                })
                .userDetailsService(userDetailsService)
//                .tokenStore(tokenStore)
                .authorizationCodeServices(authorizationCodeServices)
                .exceptionTranslator(webResponseExceptionTranslator);
    }
    }
    @Bean
    DaoAuthenticationProvider daoAuthenticationProvider(){
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setPasswordEncoder(new BCryptPasswordEncoder());
        daoAuthenticationProvider.setUserDetailsService(userDetailsService);
        return daoAuthenticationProvider;
    }
    @Bean
    @Primary
kidgrow-uaa/kidgrow-uaa-server/src/main/java/com/kidgrow/oauth2/config/SecurityConfig.java
@@ -1,6 +1,7 @@
package com.kidgrow.oauth2.config;
import com.kidgrow.common.constant.SecurityConstants;
//import com.kidgrow.oauth2.handler.InMemoryAuthenticationProvider;
import com.kidgrow.oauth2.mobile.MobileAuthenticationSecurityConfig;
import com.kidgrow.oauth2.openid.OpenIdAuthenticationSecurityConfig;
import com.kidgrow.common.config.DefaultPasswordConfig;
@@ -9,19 +10,26 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.header.HeaderWriterFilter;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
import javax.annotation.Resource;
import java.util.Arrays;
/**
@@ -63,6 +71,9 @@
    @Autowired
    private MobileAuthenticationSecurityConfig mobileAuthenticationSecurityConfig;
//    @Autowired
//    InMemoryAuthenticationProvider inMemoryAuthenticationProvider;
    /**
     * 这一步的配置是必不可少的,否则SpringBoot会自动配置一个AuthenticationManager,覆盖掉内存中的用户
     * @return 认证管理对象
@@ -72,6 +83,22 @@
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
//    @Bean
//    @Override
//    public AuthenticationManager authenticationManagerBean() throws Exception {
//        // 认证管理器中只提供我需要的两个第一个是自定义认证,第二个是数据库认证,需要经过两层认证才能通过,默认的
//
//        // 构造函数不提供自定义认证Provider,那么默认提供DaoAuthenticationProvider
//
//        ProviderManager authenticationManager = new ProviderManager(Arrays.asList(inMemoryAuthenticationProvider, daoAuthenticationProvider()));
//
//        // 不擦除认证密码,擦除会导致TokenBasedRememberMeServices因为找不到Credentials再调用UserDetailsService而抛出UsernameNotFoundException
//
//        authenticationManager.setEraseCredentialsAfterAuthentication(false);
//
//        return authenticationManager;
//    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
kidgrow-uaa/kidgrow-uaa-server/src/main/java/com/kidgrow/oauth2/handler/SingleTokenServices.java
@@ -19,6 +19,7 @@
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.*;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
//import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
@@ -30,7 +31,7 @@
@Deprecated
public class SingleTokenServices implements AuthorizationServerTokenServices, ResourceServerTokenServices, ConsumerTokenServices, InitializingBean {
    private int refreshTokenValiditySeconds = 2592000;
    private int accessTokenValiditySeconds = 3600;//43200
    private int accessTokenValiditySeconds = 10800;//43200   //登录时,给的默认值;一段时间后,用的查询数据库中的oauth_client_details的表的access_token_validity;
    private boolean supportRefreshToken = false;
    private boolean reuseRefreshToken = true;
    private TokenStore tokenStore;
@@ -166,14 +167,14 @@
    public OAuth2Authentication loadAuthentication(String accessTokenValue) throws AuthenticationException, InvalidTokenException {
        OAuth2AccessToken accessToken = this.tokenStore.readAccessToken(accessTokenValue);
        if (accessToken == null) {
            throw new InvalidTokenException("Invalid access token: " + accessTokenValue);
            throw new InvalidTokenException("Invalid access token:1 " + accessTokenValue);
        } else if (accessToken.isExpired()) {
            this.tokenStore.removeAccessToken(accessToken);
            throw new InvalidTokenException("Access token expired: " + accessTokenValue);
        } else {
            OAuth2Authentication result = this.tokenStore.readAuthentication(accessToken);
            if (result == null) {
                throw new InvalidTokenException("Invalid access token: " + accessTokenValue);
                throw new InvalidTokenException("Invalid access token:2 " + accessTokenValue);
            } else {
                if (this.clientDetailsService != null) {
                    String clientId = result.getOAuth2Request().getClientId();
@@ -193,7 +194,7 @@
    public String getClientId(String tokenValue) {
        OAuth2Authentication authentication = this.tokenStore.readAuthentication(tokenValue);
        if (authentication == null) {
            throw new InvalidTokenException("Invalid access token: " + tokenValue);
            throw new InvalidTokenException("Invalid access token:3 " + tokenValue);
        } else {
            OAuth2Request clientAuth = authentication.getOAuth2Request();
            if (clientAuth == null) {
kidgrow-web/kidgrow-web-manager/src/main/resources/static/assets/js/common.js
@@ -294,9 +294,18 @@
function permissionsInput(res,config) {
    if(!strUtil.isEmpty(res)&&res.code==401){
        config.removeToken();
        layer.msg('登录过期', {icon: 2, time: 1500}, function () {
            location.replace('/login.html');
        }, 1000);
        console.log(res);
        debugger
        if(res.msg.includes("Access token expired")){
            layer.msg('登录过期11', {icon: 2, time: 1500}, function () {
                location.replace('/login.html');
            }, 5000);
        }else{
            layer.msg('您的账号在其他地方登陆,请重新登录或修改密码', {icon: 2, time: 1500}, function () {
                location.replace('/login.html');
            }, 5000);
        }
        return;
    }
    var needpPermissions = $(".permissions");
kidgrow-web/kidgrow-web-manager/src/main/resources/static/module/admin.js
@@ -128,9 +128,20 @@
                if (jsonRs) {
                    if (jsonRs.code == 401) {
                        config.removeToken();
                        layer.msg('登录过期', {icon: 2, time: 1500}, function () {
                            location.replace('/login.html');
                        }, 1000);
                        // var json=JSON.stringify(jsonRs)
                        // console.log(json,"jsonjsonjsonjsonjsonjsonjson")
                        debugger
                        var msg=jsonRs.msg;
                        if(msg.includes("Access token expired")){
                            layer.msg('登录过期', {icon: 2, time: 1500}, function () {
                                location.replace('/login.html');
                            }, 5000);
                        }else if(msg.includes("Invalid access token")){
                            layer.msg('您的账号在其他地方登陆,请重新登录或修改密码', {icon: 2, time: 1500}, function () {
                                location.replace('/login.html');
                            }, 5000);
                        }
                        return;
                    } else if (jsonRs.code == 403) {
                        layer.msg('没有权限', {icon: 2});
kidgrow-web/kidgrow-web-manager/src/main/resources/static/module/apiUrl.js
@@ -2,5 +2,6 @@
  // var my_api_server_url = 'http://192.168.2.240:8888/';
var my_api_server_url = 'http://127.0.0.1:8888/';
// var my_api_server_url = 'http://uat-zuul.kidgrow.cloud/';
// var my_api_server_url = 'https://zuul.kidgrow.cloud/';
//var my_api_server_url = 'http://123.57.164.62:8888/';
kidgrow-web/kidgrow-web-manager/src/main/resources/static/pages/opration/doctor_form.html
@@ -233,7 +233,7 @@
                    });
                    // 回显user数据
                    var doctor = admin.getTempData('t_doctor');
                    if (doctor.roles) {
                    if (doctor!=null&&doctor.roles) {
                        formSelects.value('roleId', doctor.roles);
                    }
@@ -252,7 +252,7 @@
            // 正则验证格式
            eval("var reg = /^1[34578]\\d{9}$/;");
            var flag=RegExp(reg).test(content)
            var flag = RegExp(reg).test(content)
            return flag;
        }
        //判断用户名是否被使用
@@ -367,7 +367,7 @@
        //职称添加数据
        var getZhiCheng = function () {
            admin.req('api-user/sysdictionaries/findAll', JSON.stringify({
                dictionariesClassId: "1248150699682988034"
                dictionariesClassId: "DOCTOR_RANK"
            }), function (data) {
                layer.closeAll('loading');
                if (0 === data.code) {
@@ -459,7 +459,7 @@
            $("#username").blur(function () {
                username_is_usered("username");
            })
            //医生类型的选择事件
            // form.on('select(doctorType)', function (data) {
            //     // console.log("eeeeeeeeeeeeeeeee");
@@ -476,14 +476,14 @@
            // })
        };
        $("#doctorTel-add").blur(function () {
                $("#username").val($("#doctorTel-add").val())
                var doctorTel_add = $("#doctorTel-add").val();
                debugger
                if (!validatorTel(doctorTel_add)) {
                    layer.msg("请输入正确的手机号");
                }
                username_is_usered("username");
            })
            $("#username").val($("#doctorTel-add").val())
            var doctorTel_add = $("#doctorTel-add").val();
            debugger
            if (!validatorTel(doctorTel_add)) {
                layer.msg("请输入正确的手机号");
            }
            username_is_usered("username");
        })
        //自动完成-医院名称
        autocomplete.render({
            elem: $('#hospitalName')[0],
@@ -502,28 +502,39 @@
        form.on('select(doctorType)', function (data) {
            var doctor = admin.getTempData('t_doctor');
            var doctorType = $('#doctorType').val();
            if (doctor.doctorType == 2 && doctorType == 2) {
                $(".account").hide();
                $("#roleId_div").hide()
            } else if (doctor.doctorType == 2 && doctorType != 2) {
                $(".account").show();
                $("#password_div").show();
                $("#passwordSure_div").show();
                $("#roleId_div").show()
                if (doctor.username == null) {
                    $("#username").val(doctor.doctorTel);
                    form.render();
            if (doctor == null) {
                if (doctorType != 2) {
                    $(".account").show();
                    $("#password_div").show();
                    $("#passwordSure_div").show();
                    $("#roleId_div").show()
                }else{
                    $(".account").hide();
                    $("#roleId_div").hide()
                }
            } else if (doctor.doctorType != 2 && doctorType != 2) {
                $(".account").show();
                $("#password_div").hide();
                $("#passwordSure_div").hide();
                $("#roleId_div").show()
            } else if (doctor.doctorType != 2 && doctorType == 2) {
                $(".account").hide();
                $("#roleId_div").hide()
            } else {
                if (doctor.doctorType == 2 && doctorType == 2) {
                    $(".account").hide();
                    $("#roleId_div").hide()
                } else if (doctor.doctorType == 2 && doctorType != 2) {
                    $(".account").show();
                    $("#password_div").show();
                    $("#passwordSure_div").show();
                    $("#roleId_div").show()
                    if (doctor.username == null) {
                        $("#username").val(doctor.doctorTel);
                        form.render();
                    }
                } else if (doctor.doctorType != 2 && doctorType != 2) {
                    $(".account").show();
                    $("#password_div").hide();
                    $("#passwordSure_div").hide();
                    $("#roleId_div").show()
                } else if (doctor.doctorType != 2 && doctorType == 2) {
                    $(".account").hide();
                    $("#roleId_div").hide()
                }
            }
        })
        //数据的回显
        var doctor = admin.getTempData('t_doctor');