spring security 初探(不建议)

总体来说,比shiro要简单的多。这篇文章不好,用到的数据库不适合,看springsecurity的第2篇

 https://www.cnblogs.com/zhengqing/p/11670991.html

1. 建立springboot项目,加入spring security的pom。

2. 写配置类,config。

3. 写web的控制器。

4. 写jsp页面

5. 数据库表共5个, 

 


 

pom

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

 

配置类

继承web安全配置适配器类,enableGlobalMethodSecurity开启拦截,建立内存用户,用BCrypt动态加密,重写http的配置方法

package cn.taotao.config;


@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)   // 开启拦截
public class security extends WebSecurityConfigurerAdapter {


    @Override
    @Bean
    public UserDetailsService userDetailsServiceBean() throws Exception {
        //return super.userDetailsServiceBean();
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
// 给用户分配p1资源权限,配合控制器的注解来实现 manager.createUser(User.withUsername(
"xuyong").password("$2a$10$zBZTNl3yYKoAkH446zbz2OscgPIZ8lMSisSpZs2GFgUrHSM7JlySW").authorities("p1").build()); return manager; } @Bean public PasswordEncoder passwordEncoder(){ //return NoOpPasswordEncoder.getInstance(); return new BCryptPasswordEncoder(); }
// 重写配置类,关键,配置登录的页面,退出的页面 @Override
protected void configure(HttpSecurity http) throws Exception { // super.configure(http); http.authorizeRequests()
// .antMatchers("/r/r1").hasAuthority("p1") 这段代码可以在控制器注解中指定 .antMatchers("/**").authenticated() .anyRequest().permitAll() .and() .formLogin() .loginPage("/login-view") .loginProcessingUrl("/login") .successForwardUrl("/login-success") .permitAll() .and() .logout() .logoutUrl("/logout") .logoutSuccessUrl("/login-view") // .logoutRequestMatcher(new AntPathRequestMatcher("logout","GET")) 实现logout,避免csrf报404错误 .permitAll() ; } }

 

测试类代码,产生Bcrypt的密码

 @Test
    void Bcrty(){
        String hashpw = BCrypt.hashpw("123", BCrypt.gensalt());
        System.out.println("hashpw:"+ hashpw);

//        boolean checkpw = BCrypt.checkpw("123", "$2a$10$dbdH8C7VoyCAlJaOAuxZluUTqUNbyi4PHsWi24Y.Uaa2bCwsfOkWG");
       // $2a$10$6UWJCso9Z4dBpYjeJH.p8emRO/.UBSdgH1Opyo1mc7QSmvXt28Nxa

    }

 

控制器

@Controller
public class IndexController {


    @RequestMapping("/")
    @ResponseBody
    public String index() {
        return "index";
    }

    @ResponseBody
    @RequestMapping("/r/r1")
    @PreAuthorize("hasAuthority('p1')")       // 实现p1的控制权限
    public String r1() {
        return "r1";
    }


    @ResponseBody
    @RequestMapping("/r/r2")
    @PreAuthorize("hasAuthority('p2')")
    public String r2(){
        return "r2";
    }

    @RequestMapping("/login-success")
    public String loginsuccess(){
        return "login-success";
    }


    @RequestMapping("/login-view")
    public String loginView(){
        return "login-view";
    }


    @RequestMapping("/logout-view")
    public String logout(){
        return  "logout";
    }
}

 

代码html登录页面

<form action="login" method="post" >
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}">
    username : <input type="text" name="username">
    ps:<input type="password" name="password">
    <input type="submit">
</form>

 

#########################################

改造为sql版,建立5张表,

/*
SQLyog Ultimate v11.27 (32 bit)
MySQL - 5.7.33 : Database - security
*********************************************************************
*/


/*!40101 SET NAMES utf8 */;

/*!40101 SET SQL_MODE=''*/;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`security` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `security`;

/*Table structure for table `t_permission` */

DROP TABLE IF EXISTS `t_permission`;

CREATE TABLE `t_permission` (
  `id` varchar(32) NOT NULL,
  `code` varchar(32) DEFAULT NULL,
  `description` varchar(64) DEFAULT NULL,
  `url` varchar(128) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `t_permission` */

insert  into `t_permission`(`id`,`code`,`description`,`url`) values ('1','p1','测试资源1','/r/r1'),('2','p3','测试资源2','/r/r2');

/*Table structure for table `t_role` */

DROP TABLE IF EXISTS `t_role`;

CREATE TABLE `t_role` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `role_name` varchar(255) DEFAULT NULL,
  `description` varchar(255) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  `status` char(1) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `t_role` */

/*Table structure for table `t_role_permission` */

DROP TABLE IF EXISTS `t_role_permission`;

CREATE TABLE `t_role_permission` (
  `role_id` varchar(128) NOT NULL,
  `permission_id` varchar(128) NOT NULL,
  PRIMARY KEY (`role_id`,`permission_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `t_role_permission` */

/*Table structure for table `t_user` */

DROP TABLE IF EXISTS `t_user`;

CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `fullname` varchar(255) DEFAULT NULL,
  `mobile` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `t_user` */

/*Table structure for table `t_user_role` */

DROP TABLE IF EXISTS `t_user_role`;

CREATE TABLE `t_user_role` (
  `user_id` varchar(32) NOT NULL,
  `role_id` varchar(32) NOT NULL,
  `create_time` datetime DEFAULT NULL,
  `creator` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`user_id`,`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `t_user_role` */

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

 

建立这个包,需要屏蔽掉上面第一段中的config 中的UserDetailsService,另外新建类,从数据库中根据id查找权限,得到的是list,然后把list转换为数组,生成UserDetails,返回。

package com.itheima.security.springboot.service;

import com.itheima.security.springboot.dao.UserDao;
import com.itheima.security.springboot.model.UserDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
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;

import java.util.List;

/**
 * @author Administrator
 * @version 1.0
 **/
@Service
public class SpringDataUserDetailsService implements UserDetailsService {

    @Autowired
    UserDao userDao;

    //根据 账号查询用户信息
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        //将来连接数据库根据账号查询用户信息
        UserDto userDto = userDao.getUserByUsername(username);
        if(userDto == null){
            //如果用户查不到,返回null,由provider来抛出异常
            return null;
        }
        //根据用户的id查询用户的权限
        List<String> permissions = userDao.findPermissionsByUserId(userDto.getId());
        //将permissions转成数组
        String[] permissionArray = new String[permissions.size()];
        permissions.toArray(permissionArray);
        UserDetails userDetails = User.withUsername(userDto.getUsername()).password(userDto.getPassword()).authorities(permissionArray).build();
        return userDetails;
    }
}

 

 另外需要一个dto的包,对应于上面的那个userDao的查找权限方法

package com.itheima.security.springboot.dao;

import com.itheima.security.springboot.model.PermissionDto;
import com.itheima.security.springboot.model.UserDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Administrator
 * @version 1.0
 **/
@Repository
public class UserDao {

    @Autowired
    JdbcTemplate jdbcTemplate;

    //根据账号查询用户信息
    public UserDto getUserByUsername(String username){
        String sql = "select id,username,password,fullname,mobile from t_user where username = ?";
        //连接数据库查询用户
        List<UserDto> list = jdbcTemplate.query(sql, new Object[]{username}, new BeanPropertyRowMapper<>(UserDto.class));
        if(list !=null && list.size()==1){
            return list.get(0);
        }
        return null;
    }

    //根据用户id查询用户权限
    public List<String> findPermissionsByUserId(String userId){
        String sql = "SELECT * FROM t_permission WHERE id IN(\n" +
                "\n" +
                "SELECT permission_id FROM t_role_permission WHERE role_id IN(\n" +
                "  SELECT role_id FROM t_user_role WHERE user_id = ? \n" +
                ")\n" +
                ")\n";

        List<PermissionDto> list = jdbcTemplate.query(sql, new Object[]{userId}, new BeanPropertyRowMapper<>(PermissionDto.class));
        List<String> permissions = new ArrayList<>();
        list.forEach(c -> permissions.add(c.getCode()));
        return permissions;
    }
}

 

posted @ 2022-03-17 10:20  琴声清幽  阅读(271)  评论(0编辑  收藏  举报