美文网首页
SpringBoot整合Spring Security 基于数据

SpringBoot整合Spring Security 基于数据

作者: 伍陆柒_ | 来源:发表于2019-10-18 10:16 被阅读0次

    部分引自 www.javaboy.org
    测试数据库脚本

    /*
    Navicat MySQL Data Transfer
    Source Server         : localhost
    Source Server Version : 50717
    Source Host           : localhost:3306
    Source Database       : security
    Target Server Type    : MYSQL
    Target Server Version : 50717
    File Encoding         : 65001
    Date: 2018-07-28 15:26:51
    */
    
    SET FOREIGN_KEY_CHECKS=0;
    
    -- ----------------------------
    -- Table structure for role
    -- ----------------------------
    DROP TABLE IF EXISTS `role`;
    CREATE TABLE `role` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(32) DEFAULT NULL,
      `nameZh` varchar(32) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of role
    -- ----------------------------
    INSERT INTO `role` VALUES ('1', 'dba', '数据库管理员');
    INSERT INTO `role` VALUES ('2', 'admin', '系统管理员');
    INSERT INTO `role` VALUES ('3', 'user', '用户');
    
    -- ----------------------------
    -- Table structure for user
    -- ----------------------------
    DROP TABLE IF EXISTS `user`;
    CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(32) DEFAULT NULL,
      `password` varchar(255) DEFAULT NULL,
      `enabled` tinyint(1) DEFAULT NULL,
      `locked` tinyint(1) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of user
    -- ----------------------------
    INSERT INTO `user` VALUES ('1', 'root', '$2a$10$WuUO9k/3LfTGzMEAKxNtAenttd9ulTq7wTj17ojqbU44Q5rwN/mWu', '1', '0');
    INSERT INTO `user` VALUES ('2', 'admin', '$2a$10$WuUO9k/3LfTGzMEAKxNtAenttd9ulTq7wTj17ojqbU44Q5rwN/mWu', '1', '0');
    INSERT INTO `user` VALUES ('3', 'sang', '$2a$10$WuUO9k/3LfTGzMEAKxNtAenttd9ulTq7wTj17ojqbU44Q5rwN/mWu', '1', '0');
    
    -- ----------------------------
    -- Table structure for user_role
    -- ----------------------------
    DROP TABLE IF EXISTS `user_role`;
    CREATE TABLE `user_role` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `uid` int(11) DEFAULT NULL,
      `rid` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of user_role
    -- ----------------------------
    INSERT INTO `user_role` VALUES ('1', '1', '1');
    INSERT INTO `user_role` VALUES ('2', '1', '2');
    INSERT INTO `user_role` VALUES ('3', '2', '2');
    INSERT INTO `user_role` VALUES ('4', '3', '3');
    SET FOREIGN_KEY_CHECKS=1;
    

    注意:密码可以自己用security产生,这里偷个懒,写成了一样的,测试时不影响
    IDEA新建项目
    添加web,security,mysql driver,mybatis 依赖
    添加数据库版本和druid连接池依赖

            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>1.1.10</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
                <version>5.1.47</version>
            </dependency>
    

    application.properties

    spring.datasource.url=jdbc:mysql:///security_test
    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
    spring.datasource.username=root
    spring.datasource.password=root
    

    创建实体类User
    权限验证要求我们将用户类实现一个接口 UserDetails

    package org.javaboy.security_db.bean;
    
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    import org.springframework.security.core.userdetails.UserDetails;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.List;
    
    public class User implements UserDetails {
        private Integer id;
        private String username;
        private String password;
        private Boolean enabled;
        private Boolean locked;
        private List<Role> roles;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        @Override
        public String getUsername() {
            return username;
        }
    
        /**
         * 账号是否未过期,正常是数据库有相应字段,若过期返回false,未过期返回true
         * 我们的数据库因为没有设置该字段,所以我们直接写true
         * @return
         */
        @Override
        public boolean isAccountNonExpired() {
            return true;
        }
    
        /**
         * 账号是否未锁定,我们数据库中有该字段,所以直接返回我们的字段即可
         * 同时删除对应的get方法,因为这个方法相当于get
         * enabled同理
         * @return
         */
        @Override
        public boolean isAccountNonLocked() {
            return !locked;
        }
    
        /**
         * 凭证(密码)是否过期
         * @return
         */
        @Override
        public boolean isCredentialsNonExpired() {
            return true;
        }
    
        @Override
        public boolean isEnabled() {
            return enabled;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        /**
         * 返回用户的所有角色
         * @return
         */
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            // 将roles进行整理
            List<SimpleGrantedAuthority> authorities = new ArrayList<>();
            for (Role role : roles) {
                // 角色认证的要求,角色名必须是ROLE开始的(如果数据库中查出来的数据就是ROLE开始,该字符串可以省略)
                authorities.add(new SimpleGrantedAuthority("ROLE_"+role.getName()));
            }
            return authorities;
        }
    
        @Override
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public void setEnabled(Boolean enabled) {
            this.enabled = enabled;
        }
    
        public void setLocked(Boolean locked) {
            this.locked = locked;
        }
    
        public List<Role> getRoles() {
            return roles;
        }
    
        public void setRoles(List<Role> roles) {
            this.roles = roles;
        }
    }
    

    Role

    package org.javaboy.security_db.bean;
    
    public class Role {
        private Integer id;
        private String name;
        private String nameZh;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getNameZh() {
            return nameZh;
        }
    
        public void setNameZh(String nameZh) {
            this.nameZh = nameZh;
        }
    }
    

    准备Service和Mapper

    service

    package org.javaboy.security_db.service;
    
    import org.javaboy.security_db.bean.User;
    import org.javaboy.security_db.mapper.UserMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Service;
    
    @Service
    public class UserService implements UserDetailsService { // Service也需要实现一个接口
    
        @Autowired
        UserMapper userMapper;
        /**
         * 根据用户名返回用户信息
         * @param s 用户名
         * @return
         * @throws UsernameNotFoundException
         */
        @Override
        public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
            User user = userMapper.loadUserByUsername(s);
            if (user == null) {
                throw new UsernameNotFoundException("用户不存在");
            }
            user.setRoles(userMapper.getRolesById(user.getId()));
            return user;
        }
    }
    

    mapper

    package org.javaboy.security_db.mapper;
    
    import org.apache.ibatis.annotations.Mapper;
    import org.javaboy.security_db.bean.Role;
    import org.javaboy.security_db.bean.User;
    
    import java.util.List;
    
    @Mapper
    public interface UserMapper {
        User loadUserByUsername(String username);
        List<Role> getRolesById(Integer id);
    }
    

    mapper.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="org.javaboy.security_db.mapper.UserMapper">
        <select id="loadUserByUsername" resultType="org.javaboy.security_db.bean.User">
            select * from user where username = #{username}
        </select>
    
        <select id="getRolesById" resultType="org.javaboy.security_db.bean.Role">
            select *
            from role
            where id in (select rid from user_role where uid = #{uid})
        </select>
    </mapper>
    

    这里因为数据量比较小,采取了in
    security配置类

    package org.javaboy.security_db.config;
    
    import org.javaboy.security_db.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    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.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        UserService userService;
    
        /**
         * 指定userService
         * @param auth
         * @throws Exception
         */
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userService);
        }
        @Bean
        PasswordEncoder passwordEncoder(){
            return new BCryptPasswordEncoder();
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .antMatchers("/admin/**").hasRole("admin")
                    .antMatchers("/dba/**").hasRole("dba")
                    .antMatchers("/user/**").hasRole("user")
                    .anyRequest().authenticated()
                    .and()
                    .formLogin()
                    .permitAll()
                    .and()
                    .csrf().disable();
        }
    }
    
    

    pom配置资源目录

            <resources>
                <resource>
                    <directory>src/main/resources</directory>
                </resource>
                <resource>
                    <directory>src/main/java</directory>
                    <includes>
                        <include>**/*.xml</include>
                    </includes>
                </resource>
            </resources>
    

    准备controller接口

    package org.javaboy.security_db.controller;
    
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class HelloController {
    
        @GetMapping("/hello")
        public String hello() {
            return "hello security";
        }
    
        @GetMapping("/admin/hello")
        public String admin() {
            return "hello admin";
        }
    
        @GetMapping("/dba/hello")
        public String dba() {
            return "hello dba";
        }
    
        @GetMapping("/user/hello")
        public String user() {
            return "hello user";
        }
    }
    

    启动项目测试

    相关文章

      网友评论

          本文标题:SpringBoot整合Spring Security 基于数据

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