zoukankan      html  css  js  c++  java
  • spring security 自动登录 --- 心得

    1.前言

      仍然是使用cookie存储登录数据,但是存储的数据 由 spring security自动创建 ,当登出后自动删除cookie, 

    如果不登出也仍在生命周期内,关闭浏览器再打开将会自动登录,无需手动再登录。

    2.操作

    需要在设置有spring security 的spring boot 工程基础上【详细可查看我的其他随笔,有详细记载,具体操作这里不解释】加上下面配置 

    (1)

    security 配置里有两种写法 【但是只能选择一种】

    方法一: 使用注解风格的Java配置

     完整的security配置

    package com.example.security5500.securityConfig;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.builders.WebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.NoOpPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
    import org.springframework.stereotype.Component;
    
    //这个加不加无所谓
    @Configuration
    //开启security自定义配置
    @EnableWebSecurity
    //开启 Controller层的访问方法权限,与注解@PreAuthorize("hasRole('ROLE_admin')")配合,会拦截注解了@PreAuthrize注解的配置
    // 想要@PreAuthorize正确执行 ,权限关键字必须带前缀 ROLE_  ,后面的部分可以随便写!!!!靠,琢磨了4小时了 ,终于找到原因了
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    //, securedEnabled = true
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        //实例自定义登录校验接口 【内部有 数据库查询】
        @Autowired
        private DbUserDetailsService dbUserDetailsService;
    
    //    @Bean
    //    @Override
    //    protected AuthenticationManager authenticationManager() throws Exception {
    //        return super.authenticationManager();
    //    }
    
    
    
        //忽略拦截的静态文件路径
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring()
                    .antMatchers(
                            "/js/**",
                            "/css/**",
                            "/img/**",
                            "/webjars/**");
        }
    
        //拦截规则设置
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    //允许基于使用HttpServletRequest限制访问
                    //即授权请求设置
                    .authorizeRequests()
                    //设置不拦截页面,可直接通过,路径访问 "/", "/index",  则不拦截,
                    .antMatchers("/", "/index", "/hhk/**")
                    //是允许所有的意思
                    .permitAll()
    //                //访问 /hai 需要admin权限 ,无权限则提示 403
    //                .antMatchers("/hai").hasAuthority("admin")
    //                //访问 /kk 需要admin或user权限 ,无权限则提示 403
    //                .antMatchers("/kk").hasAnyAuthority("admin", "user")
    //                //路径/admin/**所有的请求都需要admin权限 ,无权限则提示 403
    //                .antMatchers("/admin/**").hasAuthority("admin")
                    //其他页面都要拦截,【需要在最后设置这个】
                    .anyRequest().authenticated()
                    .and()
                    //设置自定义登录页面
                    //即开启登录设置
                    .formLogin()
                    //指定自定义登录页面的访问虚拟路径
                    .loginPage("/login")
                    .permitAll()
                    .and()
    //        添加退出登录支持。当使用WebSecurityConfigurerAdapter时,这将自动应用。默认情况是,访问URL”/ logout”,使HTTP Session无效
    //        来清除用户,清除已配置的任何#rememberMe()身份验证,清除SecurityContextHolder,然后重定向到”/login?success”
                    //即开启登出设置
                    .logout()
    //                //指定的登出操作的虚拟路径,需要以post方式请求这个 http://localhost:5500/mylogout 才可以登出 ,也可以直接清除用户认证信息达到登出目的
    //                .logoutUrl("/mylogout")
                    //使httpsession失效
                    .invalidateHttpSession(true)
                    //清除认证信息
                    .clearAuthentication(true)
                    //登出请求匹配器,新建一个蚂蚁路径请求匹配器 ,与 .logoutUrl("/mylogout")效果一样
                    .logoutRequestMatcher(new AntPathRequestMatcher("/mylogout"))
                    //登出成功后访问的地址
                    .logoutSuccessUrl("/home")
                    .permitAll()
                    .and()
                    //开启记住我设置,用于自动登录
                    .rememberMe()
                    //密钥
                    .key("unique-and-secret")
                    //存在cookie的用户名[用于cookie名]
                    .rememberMeCookieName("remember-me-cookie-name")
                    //生命周期,单位毫秒
                    .tokenValiditySeconds(24 * 60 * 60);
            //登陆后"选择记住我" ,会生成cookie  ,登出则会自动删除该cookie  , 只要不登出且未超出生命周期 ,那么关闭浏览器后再次访问将自动登录
            //  [name]                          [value]                                                     [domain]   [path]      [expires/max-age]     [size]   [httponly]   [priority]
            //remember-me-cookie-name    eGk6MTU5MTIwODAzNDk5MTozZWUyN2FlMmEwMWQxNDczMDhhY2ZkYTAxZWQ5ZWQ5YQ    localhost    /       2020-06-03T18:13:54.992Z    89       ✓            Medium
    
    
        }
    
    
        /**
         * 添加 UserDetailsService, 实现自定义登录校验,数据库查询
         */
        @Override
        protected void configure(AuthenticationManagerBuilder builder) throws Exception {
            //注入用户信息,每次登录都会来这查询一次信息,因此不建议每次都向mysql查询,应该使用redis
            //密码加密
            builder.userDetailsService(dbUserDetailsService);
    //                .passwordEncoder(passwordEncoder());
        }
    
        /**
         * BCryptPasswordEncoder相关知识:
         * 用户表的密码通常使用MD5等不可逆算法加密后存储,为防止彩虹表破解更会先使用一个特定的字符串(如域名)加密,然后再使用一个随机的salt(盐值)加密。
         * 特定字符串是程序代码中固定的,salt是每个密码单独随机,一般给用户表加一个字段单独存储,比较麻烦。
         * BCrypt算法将salt随机并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理salt问题。
         */
        @Bean
        public BCryptPasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    
    
    //    /**
    //     * 选择加密方式 ,密码不加密的时候选择 NoOpPasswordEncoder,不可缺少,否则报错
    //     * java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
    //     */
    //    @Bean
    //    public static PasswordEncoder passwordEncoder() {
    //        return NoOpPasswordEncoder.getInstance();
    //    }
    
    
    }
    View Code

    方法二: xml风格

     

     xml源码

    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns="http://www.springframework.org/schema/security"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns:beans="http://www.springframework.org/schema/beans"
                 xsi:schemaLocation="http://www.springframework.org/schema/security
                                     http://www.springframework.org/schema/security/spring-security.xsd
                                     http://www.springframework.org/schema/beans
                                     http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <http>
            <!--设置不拦截的路径-->
            <!--        登录路径-->
            <intercept-url pattern="/login" access="permitAll()"/>
            <!--        静态文件路径-->
            <intercept-url pattern="/js/**" access="permitAll()"/>
            <intercept-url pattern="/css/**" access="permitAll()"/>
            <intercept-url pattern="/img/**" access="permitAll()"/>
            <intercept-url pattern="/webjars/**" access="permitAll()"/>
            <!--     设置路径需要的指定权限   -->
            <intercept-url pattern="/hai" access="hasAuthority('admin')"/>
    
            <!--        其他路径都需要拦截认证-->
            <intercept-url pattern="/**" access="isAuthenticated()"/>
            <!--Spring Security 4.0以后默认开启宽展请求伪造保护,这里配置禁用,不安全的操作。-->
            <csrf disabled="true"/>
    
            <!--        表单登录指定路径-->
            <form-login
                    login-page="/login"/>
            <!--        登出操作-->
            <!--        分别是清除session , 指定登出路径 ,指定登出成功后路径-->
            <logout
                    invalidate-session="true"
                    logout-url="/logout"
                    logout-success-url="/login?logout"/>
            <!--        记住我[自动登录]设置 -->
            <!--       三个参数分别是  密钥 ,存在cookie的用户名[用于cookie名] ,存放的生命周期[单位毫秒] -->
            <remember-me
                    key="unique-and-secret"
                    remember-me-cookie="remember-me-cookie-name"
                    token-validity-seconds="86400"/>
        </http>
    
        <!-- //在内存中进行注册公开内存的身份验证信息
        //    // 在内存中添加 用户名 ,密码 ,  权限-->
        <authentication-manager>
            <authentication-provider>
                <user-service>
                    <user name="user"
                          password="password"
                          authorities="ROLE_USER"/>
                </user-service>
            </authentication-provider>
        </authentication-manager>
    
    </beans:beans>
    View Code

    需要在启动类导入xml文件

    package com.example.security5500;
    
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    
    @SpringBootApplication
    //设置mapper接口包位置
    @MapperScan(basePackages = "com.example.security5500.dao")
    //
    // 当使用xml的方式配置时,开启此注解,将会注释掉WebSecurityConfig文件配置,该xml功能有同等效果
    // @ImportResource("classpath:security/spring-security-config.xml")
    public class Security5500Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Security5500Application.class, args);
        }
    
    
    }

    使用xml 则不可以使用 注解 @EnableWebSecurity  ,会导致失效

    (2)在前端的自定义login.html 表单里添加“记住我”的单选框标签 ,name属性不可更改

     完整源码

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
          xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Spring Security自定义</title>
    </head>
    <body>
    <div th:if="${param.error}">
        Invalid username and password.
    </div>
    <div th:if="${param.logout}">
        You have been logged out.
    </div>
    <!-- 表单的name属性不可变 -->
    <form th:action="@{/login}" method="post">
        <div><label> User Name : <input type="text" name="username"/> </label></div>
        <div><label> Password: <input type="password" name="password"/> </label></div>
        <div class="form-group">
            <label>
                <input id="remember-me"
                       name="remember-me"
                       type="checkbox"/> 记住我
            </label>
        </div>
        <div><input type="submit" value="Sign In"/></div>
    </form>
    
    <hr>
    <br>
    lalallalalal但是开发建设士大夫立刻
    </body>
    </html>
    View Code

    3.测试

    (1)启动 ,进入登录页面

     (2)勾选记住我登录 ,此时cookie只有一个jsession数据

     

     登陆后查看cookie ,多了个cookie数据

     (2)关闭浏览器再打开该网址 ,会发现可直接进入,不需要手动输入账户密码登录  

    (3)登出后,查看cookie ,会发现cookie数据没有了,只剩下jsession

  • 相关阅读:
    ZooKeeper学习第一期---Zookeeper简单介绍
    安装zookeeper(单机,伪集群)
    一张图看懂DNS域名解析全过程
    CDN基本工作过程
    第十七章、程序管理与 SELinux 初探
    直方图均衡化的缺点——不平坦
    电感耦合等离子体质谱法响应时间
    C++内容记录
    图像质量评价-NQM和WPSNR
    分颜色通道SR的相关论文
  • 原文地址:https://www.cnblogs.com/c2g5201314/p/13036082.html
Copyright © 2011-2022 走看看