ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

spring security的实现

2021-11-18 11:03:00  阅读:88  来源: 互联网

标签:return String 实现 spring private 创建 security public


目录

1. 创建springboot项目,引入maven依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--自启动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>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </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>
            <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>

2. application.properties文件对数据库进行配置

spring.datasource.druid.url=jdbc:mysql://127.0.0.1:3306/xxx
spring.datasource.druid.username=xxx
spring.datasource.druid.password=xxx
spring.datasource.druid.initialSize=1
spring.datasource.druid.minIdle=5
spring.datasource.druid.maxActive=10
spring.datasource.druid.maxWait=3000

3.根据RDBC权限模型设计数据库表

RDBC权限模型如下所示:
在这里插入图片描述

3.1 创建权限表szp_permission_test

在这里插入图片描述

3.2 创建角色权限表szp_role_permission_test

在这里插入图片描述

3.3 创建角色表szp_role_test

在这里插入图片描述

3.4 创建用户角色表szp_user_role_test

在这里插入图片描述

3.5 创建用户表szp_user_test

在这里插入图片描述

4. 创建java实体类来映射数据库中的表

4.1 创建PermissionEntity映射权限表

@Data
public class PermissionEntity {
	private Integer id;
	// 权限名称
	private String permName;
	// 权限标识
	private String permTag;
	// 请求url
	private String url;
}

4.2 创建RoleEntity映射角色表

@Data
public class RoleEntity {
	private Integer id;
	private String roleName;
	private String roleDesc;
}

4.3 创建UserEntity映射用户表

@Data
public class UserEntity implements UserDetails {

	private Integer id;
	private String username;
	private String realname;
	private String password;
	private Date createDate;
	private Date lastLoginTime;
	private boolean enabled;
	private boolean accountNonExpired;
	private boolean accountNonLocked;
	private boolean credentialsNonExpired;
	// 用户所有权限,用户表中没有这个字段,为了方便封装了这个属性
	private List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();

	public Collection<? extends GrantedAuthority> getAuthorities() {
		return authorities;
	}
}

5. 创建mapper接口对数据库进行操作

5.1 创建PermissionMapper接口对权限表进行操作

@Mapper
public interface PermissionMapper {
    @Select(" select * from szp_permission_test ")
    List<PermissionEntity> findAllPermission();
}

5.2 创建UserMapper接口对用户表进行操作

@Mapper
public interface UserMapper {
    /**
     * 根据用户名称查询
     *
     * @param userName
     * @return
     */
    @Select(" select * from szp_user_test where username = #{userName}")
    UserEntity findByUsername(@Param("userName") String userName);

    /**
     * 查询用户的权限根据用户查询权限
     *
     * @param userName
     * @return
     */
    @Select(" select permission.* from szp_user_test user" + " inner join szp_user_role_test user_role"
            + " on user.id = user_role.user_id inner join "
            + "szp_role_permission_test role_permission on user_role.role_id = role_permission.role_id "
            + " inner join szp_permission_test permission on role_permission.perm_id = permission.id where user.username = #{userName};")
    List<PermissionEntity> findPermissionByUsername(@Param("userName") String userName);
}

6.创建MemberDetailsService调用接口完成服务

@Service
public class MemberDetailsService implements UserDetailsService {
    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        //登录的时候调用该方法userName查询账户是否存在,验证账户密码
        //这时查出来的内容还不包含权限
        UserEntity userEntity = userMapper.findByUsername(userName);
        if (userEntity == null){
            return null;
        }

        //在根据该账户的userid关联查询角色对应权限,动态进行授权
        List<PermissionEntity> permissionList = userMapper.findPermissionByUsername(userName);
        //设置权限
        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        permissionList.forEach((p -> {
            // 意思相同auth.inMemoryAuthentication().withUser("add").password("add").authorities("addMember");
            grantedAuthorities.add(new SimpleGrantedAuthority(p.getPermTag()));
        }));
        userEntity.setAuthorities(grantedAuthorities);
        return userEntity;
    }
}

7. 创建工具类MD5Util

public class MD5Util {

   private static final String SALT = "mayikt";

   public static String encode(String password) {
      password = password + SALT;
      MessageDigest md5 = null;
      try {
         md5 = MessageDigest.getInstance("MD5");
      } catch (Exception e) {
         throw new RuntimeException(e);
      }
      char[] charArray = password.toCharArray();
      byte[] byteArray = new byte[charArray.length];

      for (int i = 0; i < charArray.length; i++)
         byteArray[i] = (byte) charArray[i];
      byte[] md5Bytes = md5.digest(byteArray);
      StringBuffer hexValue = new StringBuffer();
      for (int i = 0; i < md5Bytes.length; i++) {
         int val = ((int) md5Bytes[i]) & 0xff;
         if (val < 16) {
            hexValue.append("0");
         }

         hexValue.append(Integer.toHexString(val));
      }
      return hexValue.toString();
   }

   public static void main(String[] args) {
      System.out.println(MD5Util.encode("mayikt_add"));

   }
}

8. 创建配置类SecurityConfig(这个是spring security的核心)

@Component
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private MemberDetailsService memberDetailsService;
    /**
     * 新增security授权的账户
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    //这种方法写死
//        auth.inMemoryAuthentication().withUser("admin").password("admin")
//                .authorities("addMember","delMember","updateMember","showMember");
//
//        //这个账号只能访问addMember
//        auth.inMemoryAuthentication().withUser("add").password("add").authorities("addMember");
	
	//这种方法是动态的
        auth.userDetailsService(memberDetailsService).passwordEncoder(new PasswordEncoder() {//设置password编码
            @Override
            public String encode(CharSequence rawPassword) {
                return MD5Util.encode((String) rawPassword);
            }

            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                String rawPass = MD5Util.encode((String) rawPassword);
                boolean result = rawPass.equals(encodedPassword);
                return result;
            }
        });
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    	/**
         * 下面是写死的方法,不好
         */
        //配置认证方式token/form表单(这个不咋用),设置为httpBasic模式
//        http.authorizeRequests()    //拿到请求
//                .antMatchers("/**") //匹配拦截所有请求
//                .fullyAuthenticated()
//                .and()
//                .httpBasic();   //basic请求,会弹出提示框输入账号密码

//        http.authorizeRequests()    //拿到请求
//                .antMatchers("/**") //匹配拦截所有请求
//                .fullyAuthenticated()
//                .and()
//                .formLogin();   //form表单请求

//        //  /addMember接口的权限名称为addMember
//        http.authorizeRequests()
//                .antMatchers("/addMember").hasAnyAuthority("addMember")
//                .antMatchers("/delMember").hasAnyAuthority("delMember")
//                .antMatchers("/updateMember").hasAnyAuthority("updateMember")
//                .antMatchers("/showMember").hasAnyAuthority("showMember")
//                //可以允许login不被拦截
//                .antMatchers("/login").permitAll()
//                //设置自定义登录页面
//                .antMatchers("/**").fullyAuthenticated()
//                .and().formLogin();
                .loginPage("/login").and().csrf().disable();    //权限不够就跳转到/login,不知道为啥加了之后不行

        /**
         * 连接数据库动态查找权限
         */
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry authorizeRequests = http.authorizeRequests();
        //需要查询到所有的权限
        List<PermissionEntity> allPermission = permissionMapper.findAllPermission();
        allPermission.forEach((p->{
            //添加规则
            authorizeRequests.antMatchers(p.getUrl()).hasAnyAuthority(p.getPermTag());
        }));

        //可以允许login不被拦截
        authorizeRequests.antMatchers("/login").permitAll()
                //设置自定义登录页面
                .antMatchers("/**").fullyAuthenticated()
                .and().formLogin();
    }
}

9.创建配置类自定义springboot错误异常处理

/**
 * 自定义SpringBoot 错误异常
 */
@Configuration
public class WebServerAutoConfiguration {
    @Bean
    public ConfigurableServletWebServerFactory webServerFactory() {
        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
        ErrorPage errorPage400 = new ErrorPage(HttpStatus.BAD_REQUEST, "/error/400");
        ErrorPage errorPage401 = new ErrorPage(HttpStatus.UNAUTHORIZED, "/error/401");
        ErrorPage errorPage403 = new ErrorPage(HttpStatus.FORBIDDEN, "/error/403");
        ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error/404");
        ErrorPage errorPage415 = new ErrorPage(HttpStatus.UNSUPPORTED_MEDIA_TYPE, "/error/415");
        ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500");
        factory.addErrorPages(errorPage400, errorPage401, errorPage403, errorPage404, errorPage415, errorPage500);
        return factory;
    }
}

10.创建controller接口来进行测试

@RestController
public class MemberController {
    /**
     * 增加用户
     *
     * @return
     */
    @RequestMapping("/addMember")
    public String addMember() {
        return "addMember";
    }

    /**
     * 删除用户
     *
     * @return
     */
    @RequestMapping("/delMember")
    public String delMember() {
        return "delMember";
    }

    /**
     * updateMember
     *
     * @return
     */
    @RequestMapping("/updateMember")
    public String updateMember() {
        return "updateMember";
    }

    /**
     * showMember
     *
     * @return
     */
    @RequestMapping("/showMember")
    public String showMember() {
        return "showMember";
    }

    /**
     * There is no PasswordEncoder mapped for the id "null"
     * 原因:升级为Security5.0以上密码支持多中加密方式,恢复以前模式
     * @return
     */
    @Bean
    public static NoOpPasswordEncoder passwordEncoder() {
        return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
    }

}

11.效果展示

输入http://localhost:8080/addMember,会自动跳转到http://localhost:8080/login

这里输入mayikt_add用户,对应有addMember的权限
在这里插入图片描述
登录后显示已进入addMember
在这里插入图片描述

修改url为http://localhost:8080/delMember

发现无法进入,显示权限不足
在这里插入图片描述

标签:return,String,实现,spring,private,创建,security,public
来源: https://blog.csdn.net/weixin_44488616/article/details/121393749

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有