从零开始搭建springboot-security

创建springboot项目

  • 创建父工程security-oauth2-demo2
  • 创建子工程oauth2-service
  • 引入依赖
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <optional>true</optional>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
</dependency>
  • 配置文件application.yml
server:
  port: 8081
  servlet:
    context-path: /demo2
  • 创建controller
@RestController
public class UserController {

    @RequestMapping("/hello")
    public String hello(){
        return "Hello world!";
    }
}
  • 项目结构

  •  启动访问

整合security

  •  引入依赖

        <!--数据库依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>5.1.47</scope>
        </dependency>
        <!--security依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
  • 创建数据库表
CREATE TABLE `security2`.`t_user`  (
  `id` int(0) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `username` varchar(100) COMMENT '账号',
  `password` varchar(255) COMMENT '密码',
  `realname` varchar(100) CHARACTER SET utf8 COMMENT '名称',
  `auth` varchar(255) COMMENT '权限',
  PRIMARY KEY (`id`)
);
INSERT INTO `t_user` VALUES (1, 'zhangsan', '123', '张三', 'p1');
INSERT INTO `t_user` VALUES (2, 'lisi', '202CB962AC59075B964B07152D234B70', '李四', 'p2');
  • application.yml添加数据库配置
server:
  port: 8081
  servlet:
    context-path: /demo2
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    validation-query: SELECT 1
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/security2?useUnicode=true&characterEncoding=utf-8
  • 创建dao查询数据库
package com.security.oauth2.oauth2service.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.Map;

@Repository
public class UserDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 根据账号查询
     * @return
     */
    public Map<String,Object> getUserByUsername(String userName){
        String sql = "select * from t_user where username=?";
        Map<String, Object> user = jdbcTemplate.queryForMap(sql, new Object[]{userName});
        return user;
    }

}
  • 创建MyUserDetailsService实现UserDetailsService中的登录验证方法
package com.security.oauth2.oauth2service.config.security;

import com.security.oauth2.oauth2service.dao.UserDao;
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.Component;

import java.util.Map;

/**
 *  重写登录规则,并加入容器
 */
@Component
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private UserDao userDao;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println("username:"+username);
        //从数据库查询
        Map<String,Object> dbUser = userDao.getUserByUsername(username);
        if (dbUser == null){
            return null;
        }
        //根据用户名查询用户权限
        String[] premiss = dbUser.get("auth").toString().split(",");
        UserDetails build = User
                //账号
                .withUsername(dbUser.get("username").toString())
                //密码
                .password(dbUser.get("password").toString())
                //权限
                .authorities(premiss).build();
        return build;
    }
}
  • 创建WebSecurityConfig文件继承WebSecurityConfigurerAdapter重写核心配置方法,并配置密码验证规则为不加密
package com.security.oauth2.oauth2service.config.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration //标志为一个配置文件
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder(){
        //密码规则为原始数据,不加密
        return NoOpPasswordEncoder.getInstance();
    }
    /**
     * 认证策略,核心配置,具体的权限控制规则配置
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            //设置r1路径的访问权限是 p1
            .antMatchers("/r/r1").hasAuthority("p1")
            //设置r2路径的访问权限是 p2
            .antMatchers("/r/r2").hasAuthority("p2")
            //除了 /r/**.其他请求可以访问
            .anyRequest().permitAll()
            .and()
            //开启表单登录,如果检测导没有登录会跳转到登录页
            .formLogin();
    }

}
  • controller添加访问路径
package com.security.oauth2.oauth2service.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @RequestMapping("/hello")
    public String hello(){
        return "Hello world!";
    }

    @RequestMapping("/r/r1")
    public String r1(){
        return "访问资源1!";
    }
    @RequestMapping("/r/r2")
    public String r2(){
        return "访问资源2!";
    }
}
  • 目录结构

输入账号zhangsan密码123 

点击登录

访问r2

启用权限注解

  • 修改WebSecurityConfig配置文件

1、添加注解@EnableGlobalMethodSecurity(prePostEnabled = true),意思是开启前置权限注解@PrePostEnabled的使用

2、取消r1和r2的核心配置

package com.security.oauth2.oauth2service.config.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration //标志为一个配置文件
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder(){
        //密码规则为原始数据,不加密
        return NoOpPasswordEncoder.getInstance();
    }
    /**
     * 认证策略,核心配置,具体的权限控制规则配置
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            //设置r1路径的访问权限是 p1
//            .antMatchers("/r/r1").hasAuthority("p1")
//            //设置r2路径的访问权限是 p2
//            .antMatchers("/r/r2").hasAuthority("p2")
            //请求可以访问
            .anyRequest().permitAll()
            .and()
            //开启表单登录,如果检测导没有登录会跳转到登录页
            .formLogin();
    }

}
  • 修改controller方法,添加@PrePostEnabled注解
package com.security.oauth2.oauth2service.controller;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @RequestMapping("/hello")
    public String hello(){
        return "Hello world!";
    }

    @RequestMapping("/r/r1")
    @PreAuthorize("hasAuthority('p1')")
    public String r1(){
        return "访问资源1!";
    }
    @RequestMapping("/r/r2")
    @PreAuthorize("hasAuthority('p2')")
    public String r2(){
        return "访问资源2!";
    }
}
  • 访问r1

输入账号zhangsan密码123

访问r2

 自定义密码加密规则

  • 引入md5加密util
package com.security.oauth2.oauth2service.util;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 1.MD5加密字符串(32位大写)
 * 2.MD5加密字符串(32位小写)
 * <p>
 * MD5在线加密:https://md5jiami.51240.com/
 * 3.将二进制字节数组转换为十六进制字符串
 * 4.Unicode中文编码转换成字符串
 */
public class MD5Util {

    /**
     * MD5加密字符串(32位大写)
     *
     * @param string 需要进行MD5加密的字符串
     * @return 加密后的字符串(大写)
     */
    public static String md5Encrypt32Upper(String string) {
        byte[] hash;
        try {
            //创建一个MD5算法对象,并获得MD5字节数组,16*8=128位
            hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("Huh, MD5 should be supported?", e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("Huh, UTF-8 should be supported?", e);
        }

        //转换为十六进制字符串
        StringBuilder hex = new StringBuilder(hash.length * 2);
        for (byte b : hash) {
            if ((b & 0xFF) < 0x10){
                hex.append("0");
            }
            hex.append(Integer.toHexString(b & 0xFF));
        }
        return hex.toString().toUpperCase();
    }

//    public static void main(String[] args) {
//        System.out.println(encodeMD5("123"));
//    }
    /**
     * MD5加密字符串(32位小写)
     *
     * @param string 需要进行MD5加密的字符串
     * @return 加密后的字符串(小写)
     */
    public static String md5Encrypt32Lower(String string) {
        byte[] hash;
        try {
            //创建一个MD5算法对象,并获得MD5字节数组,16*8=128位
            hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("Huh, MD5 should be supported?", e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("Huh, UTF-8 should be supported?", e);
        }

        //转换为十六进制字符串
        StringBuilder hex = new StringBuilder(hash.length * 2);
        for (byte b : hash) {
            if ((b & 0xFF) < 0x10){
                hex.append("0");
            }
            hex.append(Integer.toHexString(b & 0xFF));
        }
        return hex.toString().toLowerCase();
    }

    /**
     * 将二进制字节数组转换为十六进制字符串
     *
     * @param bytes 二进制字节数组
     * @return 十六进制字符串
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuffer hexStr = new StringBuffer();
        int num;
        for (int i = 0; i < bytes.length; i++) {
            num = bytes[i];
            if (num < 0) {
                num += 256;
            }
            if (num < 16) {
                hexStr.append("0");
            }
            hexStr.append(Integer.toHexString(num));
        }
        return hexStr.toString().toUpperCase();
    }

    /**
     * Unicode中文编码转换成字符串
     */
    public static String unicodeToString(String str) {
        Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))");
        Matcher matcher = pattern.matcher(str);
        char ch;
        while (matcher.find()) {
            ch = (char) Integer.parseInt(matcher.group(2), 16);
            str = str.replace(matcher.group(1), ch + "");
        }
        return str;
    }

    public static void main(String[] args) {
//        System.out.println(md5Encrypt32Lower("oem"));
//        System.out.println(md5Encrypt32Lower("djdqltj"));//大江东去浪淘尽
//        System.out.println(md5Encrypt32Lower("SOC_SAFE_1149"));
//        System.out.println(md5Encrypt32Lower("mhxzkhl"));//梅花香自苦寒来

//        String password = DesUtil.decrypt("670B14728AD9902AECBA32E22FA4F6BD");
//        System.out.println("password:"+password);
        System.out.println(md5Encrypt32Upper("123"));
    }
}
  • 创建MD5PasswordEncoder实现PasswordEncoder的密码验证方法
package com.security.oauth2.oauth2service.config.security;

import com.security.oauth2.oauth2service.util.MD5Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.crypto.password.PasswordEncoder;

public class MD5PasswordEncoder implements PasswordEncoder {

    private Logger logger = LoggerFactory.getLogger(MD5PasswordEncoder.class);

    @Override
    public String encode(CharSequence rawPassword) {
        if (rawPassword == null) {
            throw new IllegalArgumentException("rawPassword cannot be null");
        } else {
            return MD5Util.md5Encrypt32Upper(rawPassword.toString());
        }
    }

    /**
     * 重写密码验证规则
     */
    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        if (rawPassword == null) {
            throw new IllegalArgumentException("rawPassword cannot be null");
        } else if (encodedPassword != null && encodedPassword.length() != 0) {

            return encode(rawPassword).equals(encodedPassword);
        } else {
            this.logger.warn("Empty encoded password");
            return false;
        }
    }
    @Override
    public boolean upgradeEncoding(String encodedPassword) {
        return false;
    }
}
  • 修改WebSecurityConfig中的密码bean

  • 启动访问

登录zhangsan   123

登录lisi 123(数据库中是加密的md5串)

自定义登录页面

  • 在resources添加static包,在static包下创建login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="login" method="post">
        <input type="text" name="username" id="username"><br>
        <input type="text" name="password" id="password"><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>
  • 修改WebSecurityConfig中的核心配置方法
package com.security.oauth2.oauth2service.config.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration //标志为一个配置文件
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder(){
//        //密码规则为原始数据,不加密
//        return NoOpPasswordEncoder.getInstance();
        //密码规则为自定义md5规则
        return new MD5PasswordEncoder();
    }
    /**
     * 认证策略,核心配置,具体的权限控制规则配置
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            //解决跨域问题
            .csrf().disable()
            .authorizeRequests()
            //设置r1路径的访问权限是 p1
//            .antMatchers("/r/r1").hasAuthority("p1")
//            //设置r2路径的访问权限是 p2
//            .antMatchers("/r/r2").hasAuthority("p2")
            //请求可以访问
            .anyRequest().permitAll()
            .and()
            //开启表单登录,如果检测导没有登录会跳转到登录页
            .formLogin()
            //登录页面
            .loginPage("/login.html")
            //定义登录方法
            .loginProcessingUrl("/login")
            //自定义登录成功的页面地址
            .successForwardUrl("/login-success")
            .and()
            .sessionManagement()
            //登陆时,如果需要就创建一个session
            .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);;
    }

}
  • 添加controller方法

    @RequestMapping(value = "/login-success",produces = "text/plain;charset=UTF-8")
    public String loginSuccess(HttpServletRequest req){
        System.out.println("登录成功");
        return "登录成功";
    }
  • 启动访问 http://localhost:8081/demo2/r/r2,看会不会自动跳转到自定义页面

登录 lisi 123

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: idea-springboot-projectes是指使用IDEA开发工具构建Spring Boot项目的过程。Spring Boot是一个流行的开源框架,可以帮助Java开发者快速构建高效的微服务应用。IDEA则是一个以Java为基础的集成开发环境,可以提供代码编辑、调试、测试和部署等功能。 在构建Spring Boot项目时,IDEA可以通过自带的Spring Initializr工具或者通过手动配置的方式来进行。Spring Initializr可以自动生成项目基础框架,包括依赖库、项目结构、POM文件等。而手动配置则需要开发者自行添加所需要的依赖库和配置文件。 在项目开发过程中,IDEA可以提供强大的代码提示和自动补全功能,包括快捷键、代码重构、调试等。此外,IDEA还支持各种测试框架和部署方式,方便开发者快速进行测试和部署。 总的来说,使用IDEA开发Spring Boot项目可以提高开发效率和代码质量,并且可以使用各种插件和扩展来增强开发体验。这是一个非常流行的Java开发模式,适用于各种类型的应用程序和系统。 ### 回答2: Idea-SpringBoot-Project是一个使用了Spring Boot框架的项目,有助于Java开发者轻松构建Web应用程序。Spring Boot是一个流行的Java框架,它可以帮助开发者更快地构建更好的应用程序。使用Idea-SpringBoot-Project,开发者可以轻松创建具有高可用性和可扩展性的Java Web应用程序。 Idea-SpringBoot-Project引入了许多方便的功能,如Spring容器管理、数据访问和Web MVC框架等。通过使用Spring Boot,开发者可以在不需要手动配置的情况下快速构建应用程序。而使用Idea作为开发工具,则能帮助开发者更快地编写代码和进行调试。这个项目不仅可以在Windows和Linux平台上运行,还与许多其他大型Java库和框架兼容,如Spring Security和Hibernate等。 总之,Idea-SpringBoot-Project帮助开发者将更多的时间专注于应用程序逻辑和功能,而不是花费时间和精力去手动配置。通过这个项目,开发者可以构建出高性能、高度可用性和可扩展性的Java应用程序。 ### 回答3: idea-springboot-projectes是针对Spring Boot框架的项目管理功能的开发工具集成环境。它提供了一种方便快捷的方式来创建、维护和调试Spring Boot项目。 idea-springboot-projectes使开发人员能够在一个单一的界面中,管理不同的Spring Boot项目,包括应用程序、库和插件。它自动生成项目结构,提供依赖管理,支持代码重构、调试和测试等功能,同时也能够整合其他常用开发工具如Maven、Gradle等,进一步提升开发效率。 通过idea-springboot-projectes,开发人员可以快速创建Spring Boot应用程序。一旦项目创建完成,可以通过IDEA的自动配置机制,无需编写大量的代码即可完成基础设施的搭建和配置。同时,IDEA也提供了许多Spring Boot Starter库,这些库包含了大量常用的功能和组件,帮助开发人员轻松实现各种业务需求。 总之,idea-springboot-projectes是一款非常实用的开发工具,为Spring Boot开发提供了强大的项目管理和开发支持,同时提高了开发效率和代码质量,使得开发人员能够更专注于业务代码的编写。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值