Watch 2 Star 2 Fork 0

Jonny / single

Join us
Explore and code with more than 2 million developers,Free private repositories !:)
Sign up
This repository doesn't specify license. Without author's permission, this code is only for learning and cannot be used for other purposes.
grails+spring security实现单端登录,同一个用户在不同客户端同时登录,会把前面登录的session强制注销。 spread retract

Clone or download
Loading...
readMe.md

开发工具

Intellij IDEA 2017.2

开发环境:

| Grails Version: 3.1.5
| Groovy Version: 2.4.6
| JVM Version: 1.8.0_144

本项目为grails+spring security实现单端登录

注意:此处当用户并非单点登录,主要实现功能效果防止多端登录,一方登录,另一方强制下线。

创建项目(略)

项目创建完成后,在build.gradle中引入spring security依赖:

    buildscript {
        ext {
            grailsVersion = project.grailsVersion
        }
        repositories {
            mavenLocal()
            maven { url "https://repo.grails.org/grails/core" }
        }
        dependencies {
            classpath "org.grails:grails-gradle-plugin:$grailsVersion"
            classpath "com.bertramlabs.plugins:asset-pipeline-gradle:2.8.2"
            classpath "org.grails.plugins:hibernate4:5.0.5"
        }
    }
    
    version "0.1"
    group "springsecurity"
    
    apply plugin:"eclipse"
    apply plugin:"idea"
    apply plugin:"war"
    apply plugin:"org.grails.grails-web"
    apply plugin:"org.grails.grails-gsp"
    apply plugin:"asset-pipeline"
    
    ext {
        grailsVersion = project.grailsVersion
        gradleWrapperVersion = project.gradleWrapperVersion
    }
    
    repositories {
        mavenLocal()
        maven { url "https://repo.grails.org/grails/core" }
    }
    
    dependencyManagement {
        imports {
            mavenBom "org.grails:grails-bom:$grailsVersion"
        }
        applyMavenExclusions false
    }
    
    dependencies {
    
        //spring security权限依赖
        compile 'org.grails.plugins:spring-security-core:3.1.2'
    
        compile "org.springframework.boot:spring-boot-starter-logging"
        compile "org.springframework.boot:spring-boot-autoconfigure"
        compile "org.grails:grails-core"
        compile "org.springframework.boot:spring-boot-starter-actuator"
        compile "org.springframework.boot:spring-boot-starter-tomcat"
        compile "org.grails:grails-dependencies"
        compile "org.grails:grails-web-boot"
        compile "org.grails.plugins:cache"
        compile "org.grails.plugins:scaffolding"
        compile "org.grails.plugins:hibernate4"
        compile "org.hibernate:hibernate-ehcache"
        console "org.grails:grails-console"
        profile "org.grails.profiles:web:3.1.5"
        runtime "com.bertramlabs.plugins:asset-pipeline-grails:2.8.2"
        runtime "com.h2database:h2"
        testCompile "org.grails:grails-plugin-testing"
        testCompile "org.grails.plugins:geb"
        testRuntime "org.seleniumhq.selenium:selenium-htmlunit-driver:2.47.1"
        testRuntime "net.sourceforge.htmlunit:htmlunit:2.18"
    }
    
    task wrapper(type: Wrapper) {
        gradleVersion = gradleWrapperVersion
    }
    
    assets {
        minifyJs = true
        minifyCss = true
    }

依赖下载完成后,按住Ctrl+Alt+G,在commond里面输入:

s2-quickstart com.system User Role

他会自动帮你创建User、Role以及UserRole类,grails-app/conf/application.groovy也会自动配置好,执行完成控制台提示:

|Creating User class 'User' and Role class 'Role' in package 'com.system'
|Rendered template Person.groovy.template to destination grails-app\domain\com\system\User.groovy
|Rendered template Authority.groovy.template to destination grails-app\domain\com\system\Role.groovy
|Rendered template PersonAuthority.groovy.template to destination grails-app\domain\com\system\UserRole.groovy
|
************************************************************
* Created security-related domain classes. Your            *
* grails-app/conf/application.groovy has been updated with *
* the class names of the configured domain classes;        *
* please verify that the values are correct.               *
************************************************************

src/main/groovy下面创建packagecom.custom并创建ConcurrentSingleSessionAuthenticationStrategy

    package com.custom
    
    import org.springframework.security.core.Authentication
    import org.springframework.security.core.session.SessionRegistry
    import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy
    import org.springframework.util.Assert
    
    import javax.servlet.http.HttpServletRequest
    import javax.servlet.http.HttpServletResponse
    /**
     * 会话管理类
     * @auther Lee
     * @Date 2017/11/14 18:21
     * return
     */
    class ConcurrentSingleSessionAuthenticationStrategy implements SessionAuthenticationStrategy {
    
        private SessionRegistry sessionRegistry
    
        /**
         * @param 将新的会话赋值给sessionRegistry
         */
        public ConcurrentSingleSessionAuthenticationStrategy(SessionRegistry sessionRegistry) {
            Assert.notNull(sessionRegistry, "SessionRegistry cannot be null")
            this.sessionRegistry = sessionRegistry
        }
        /**
         * 覆盖父类的onAuthentication方法
         * 用新的session替换旧的session
         */
        public void onAuthentication(Authentication authentication, HttpServletRequest request, HttpServletResponse response) {
    
            def sessions = sessionRegistry.getAllSessions(authentication.getPrincipal(), false)
            def principals = sessionRegistry.getAllPrincipals()
            sessions.each {
                if (it.principal == authentication.getPrincipal()) {
                    it.expireNow()
                }
            }
    
    
        }
    }

打开grails-app/conf/spring/resource.groovy,配置DSL,注意导包

    import com.custom.ConcurrentSingleSessionAuthenticationStrategy
    import org.springframework.security.core.session.SessionRegistryImpl
    import org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy
    import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy
    import org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy
    import org.springframework.security.web.session.ConcurrentSessionFilter
    
    // Place your Spring DSL code here
    beans = {
    
        sessionRegistry(SessionRegistryImpl)
        //很重要
        sessionFixationProtectionStrategy(SessionFixationProtectionStrategy){
            migrateSessionAttributes = true
            alwaysCreateSession = true
        }
        // "/login/already"为重定向请求
        concurrentSingleSessionAuthenticationStrategy(ConcurrentSingleSessionAuthenticationStrategy,ref('sessionRegistry'))
        registerSessionAuthenticationStrategy(RegisterSessionAuthenticationStrategy,ref('sessionRegistry'))
        sessionAuthenticationStrategy(CompositeSessionAuthenticationStrategy,[ref('concurrentSingleSessionAuthenticationStrategy'), ref('sessionFixationProtectionStrategy'), ref('registerSessionAuthenticationStrategy')])
        concurrentSessionFilter(ConcurrentSessionFilter, ref('sessionRegistry'), "/login/already")
        
        // grails3.3.0用下面这个,查看源码发现ConcurrentSessionFilter类中重定向url的构造方法已被废弃,不生效
        //concurrentSessionFilter(ConcurrentSessionFilter, ref('sessionRegistry'))
    }

打开grails-app/conf/application.groovy,最后面加入

    grails.plugin.springsecurity.filterChain.filterNames = [ 'securityContextPersistenceFilter', 'logoutFilter', 'concurrentSessionFilter', 'rememberMeAuthenticationFilter', 'anonymousAuthenticationFilter', 'exceptionTranslationFilter', 'filterInvocationInterceptor' ]

init/BootStrap.groovy下面的init方法中添加启动任务,注意添加构造方法

    import com.system.Role
    import com.system.User
    import com.system.UserRole
    
    class BootStrap {
    
        def init = { servletContext ->
    
            //创建角色
            def role1 = new Role(authority: "ROLE_ADMIN").save()
            def role2 = new Role(authority: "ROLE_SUPSYS").save()
            def role3 = new Role(authority: "ROLE_USER").save()
    
            //创建用户
            def user1 = new User(username: "admin", password: "admin").save()
            def user2 = new User(username: "super", password: "super").save()
            def user3 = new User(username: "user", password: "user").save()
    
            //用户角色关联
            UserRole.create user1, role1, true
            UserRole.create user2, role2, true
            UserRole.create user3, role3, true
        }
        def destroy = {
    
        }
    }
    

启动项目,访问http://localhost:8080

常见问题:

  • 启动报错====>配置问题

  • 无法登陆====>有可能用户密码未加密,请加密后再次运行

  • 没有LoginControllerauth.gsp怎么办?

    1. 找到spring-security-core包
    2. 拷贝login到你项目的views下面,可以自行修改样式
    3. 拷贝grails/plugin/springsecurity/LoginController到你项目的controller下面,自己建包

参考地址

参考一 参考二

Comments ( 0 )

Sign in for post a comment

1
https://gitee.com/GntLee/single.git
git@gitee.com:GntLee/single.git
GntLee
single
single
master

Help Search