美文网首页
Spring Security(Mysql)

Spring Security(Mysql)

作者: 凌康ACG | 来源:发表于2019-11-17 14:53 被阅读0次

    Spring Security基于Mysql身份验证(自定义认证,基于角色),由于业务的复杂性我们不可能使用spring官网的example来做认证,本次主要是重写security的认证方式,阅读源码即可实现。
    下一篇为Spring Security自定义授权:
    技术栈:
    springboot+springsecurity+mybatis所用最新框架spring5,2019年11月17日 14:51:16
    项目基于上一篇文章springsecurity内存认证授权https://www.jianshu.com/p/d71c7fa9b534

    一、首先创建项目springsecurity-mysql

    image.png
    image.png
    页面基于上篇文章:https://www.jianshu.com/p/d71c7fa9b534
    maven如下
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.2.1.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.lingkang</groupId>
        <artifactId>springsecurity-mysql</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>springsecurity-mysql</name>
        <description>2019年11月17日 15:32:40</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <!--html页面使用sec标签,属于spring5 security-->
            <dependency>
                <groupId>org.thymeleaf.extras</groupId>
                <artifactId>thymeleaf-extras-springsecurity5</artifactId>
                <version>3.0.4.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.1</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    创建数据库名称为security和两张表:用户表(se_user)、角色表(se_role):

    DROP TABLE IF EXISTS `se_role`;
    CREATE TABLE `se_role`  (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `user_id` int(11) NULL DEFAULT NULL,
      `name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `create_time` datetime(0) NULL DEFAULT NULL,
      `update_time` datetime(0) NULL DEFAULT NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of se_role
    -- ----------------------------
    INSERT INTO `se_role` VALUES (1, 1, 'vip1', '2019-11-17 15:27:04', NULL);
    INSERT INTO `se_role` VALUES (3, 2, 'vip2', '2019-11-17 15:27:26', NULL);
    INSERT INTO `se_role` VALUES (4, 2, 'vip3', '2019-11-17 15:27:35', NULL);
    INSERT INTO `se_role` VALUES (5, 3, 'vip1', '2019-11-17 15:28:00', NULL);
    INSERT INTO `se_role` VALUES (6, 3, 'vip2', '2019-11-17 15:28:08', NULL);
    INSERT INTO `se_role` VALUES (7, 3, 'vip3', '2019-11-17 15:28:16', NULL);
    
    -- ----------------------------
    -- Table structure for se_user
    -- ----------------------------
    DROP TABLE IF EXISTS `se_user`;
    CREATE TABLE `se_user`  (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `username` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `password` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `status` int(1) NULL DEFAULT NULL,
      `create_time` datetime(0) NULL DEFAULT NULL,
      `update_titme` datetime(0) NULL DEFAULT NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of se_user
    -- ----------------------------
    INSERT INTO `se_user` VALUES (1, '张三', '123', '123', 1, '2019-11-17 15:26:10', NULL);
    INSERT INTO `se_user` VALUES (2, '李四', 'user', '123', 1, '2019-11-17 15:26:28', NULL);
    INSERT INTO `se_user` VALUES (3, '管理员', 'admin', 'admin', 1, '2019-11-17 15:26:46', NULL);
    

    application.properties配置如下:

    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/security?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.username=root
    spring.datasource.password=123456
    
    #配置xml扫描
    mybatis.mapper-locations=classpath:mapper/*.xml
    

    搭建项目如下


    image.png

    二、修改代码

    创建自定义CustomUserDetailsServiceImpl :

    @Component //交给spring托管,应为我们使用@Autowired注入了spring的接口
    public class CustomUserDetailsServiceImpl implements UserDetailsService {
    
        @Autowired
        private UserService userService;
    
        @Override
        public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
            //查询用户
            SeUser user = userService.getUserInfo(s);
            if (user == null) {
                throw new UsernameNotFoundException("帐号:" + s + " 不存在!");
            }
            List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
            //查询拥有的角色
            List<SeRole> roles = userService.getUserRoleByUserId(user.getId());
            roles.forEach(r -> {
                //security的验证规则需要ROLE_,由于我数据库是vip1、vip2、vip3这种值,需要加上ROLE_
                grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_" + r.getName()));
            });
            //spring5+要求密码加密,我这里传明文密码来加密
            String password = new BCryptPasswordEncoder().encode(user.getPassword());
            return new User(user.getUsername(), password, grantedAuthorities);
        }
    
    }
    

    修改SecurityConfig:

    @EnableWebSecurity
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        //注入我们加密的方式,spring5+以上必须要加密密码,这是官网推荐的加密方式,也可选择MD5
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    
        //由于我们自定义了UserDetailsService,我们需要新注入这个bean
        @Bean
        @Override //重写
        public UserDetailsService userDetailsServiceBean() {
            //使用我们自定义的 UserDetailsService
            return new CustomUserDetailsServiceImpl();
        }
    
        //认证----自定义认证
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            //自定义认证
            auth.userDetailsService(userDetailsServiceBean());
        }
    
        //授权
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            //授权规则,除了要授权的,其他所有人能访问
            http.authorizeRequests()
                    .antMatchers("/vip1/**").hasAnyRole("vip1")
                    .antMatchers("/vip2/**").hasAnyRole("vip2")
                    .antMatchers("/vip3/**").hasAnyRole("vip3")
                    .anyRequest().permitAll(); //其他页面所有人能访问
    
            //启动登陆页面
            //定制登陆页面,表单提交的路径loginProcessingUrl
            http.formLogin().loginPage("/toLogin").loginProcessingUrl("/login");
    
            //注销功能 ,跳回首页
            //关闭跨域认证请求,否则你需要post来注销
            http.logout().logoutSuccessUrl("/")
                    .and().csrf().disable();
    
            //开启记住我功能,表单提交remember的参数
            http.rememberMe().rememberMeParameter("remember");
        }
    }
    

    项目总体如下:


    image.png

    三、效果如下:

    登录123时:


    image.png

    登录user时:


    image.png
    登录admin时:
    image.png

    想要从session中获取用户信息可以:

    SecurityContextImpl securityContextImpl = (SecurityContextImpl) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
    

    一般spring security在认证后,security会把一个SecurityContextImpl对象存储到session中,此对象中有当前用户的各种资料。
    项目源码:https://github.com/xcocean/springsecurity-mysql

    相关文章

      网友评论

          本文标题:Spring Security(Mysql)

          本文链接:https://www.haomeiwen.com/subject/dqppictx.html