Springboot2(52)集成Security5

源码地址

springboot2教程系列

添加依赖

<!--数据库相关-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.12</version>
</dependency>

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

<!--security-->
<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>

配置文件

spring:
  messages:
    basename: i18n/Messages,i18n/Pages
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource    # 配置当前要使用的数据源的操作类型
    driver-class-name: org.gjt.mm.mysql.Driver      # 配置MySQL的驱动程序类
    url: jdbc:mysql://47.106.106.53:3306/security?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8           # 数据库连接地址
    username: root                                  # 数据库用户名
    password: Rojao@123


spring.jpa.database: mysql
spring.jpa.database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
# 显示后台处理的SQL语句
spring.jpa.show-sql: true
# 自动检查实体和数据库表是否一致,如果不一致则会进行更新数据库表
spring.jpa.hibernate.ddl-auto: create
spring.jpa.open-in-view: false

Security配置类

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)  //  启用方法级别的权限认证
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyUserDetailsService myUserDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //  允许所有用户访问"/"和"/index.html"
        http.authorizeRequests()
                .antMatchers("/", "/index.html").permitAll()  //定义不需要认证就可以访问
                .antMatchers("/level1/**").hasRole("VIP1")    //需要拥有VIP1权限
                .anyRequest().authenticated()      // 其他地址的访问均需验证权限
                .and()
                //开启cookie保存用户数据
                .rememberMe()
                //设置cookie有效期
                .tokenValiditySeconds(60 * 60 * 24 * 7)
                .and()
                .formLogin()                     //  定义当需要用户登录时候,转到的登录页面
                .loginPage("/login.html")      //  登录页
                .failureUrl("/login-error.html").permitAll()
                .and()
                .logout()
                .logoutSuccessUrl("/index.html");
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
       /* auth.inMemoryAuthentication()
             .withUser("admin").password("123456").roles("USER");*/
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        //静态资源忽略认证
        web.ignoring().antMatchers("/css/**");
    }

    /**
     * 配置登录验证
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailsService).passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        // return new BCryptPasswordEncoder();
        return new MyPasswordEncoder();
    }


}

通过@EnableWebSecurity注解开启Spring Security的功能 继承WebSecurityConfigurerAdapter,并重写它的方法来设置一些web安全的细节 configure(HttpSecurity http)方法,通过authorizeRequests()定义哪些URL需要被保护、哪些不需要被保护。例如以上代码指定了/和/home不需要任何认证就可以访问,其他的路径都必须通过身份验证。 通过formLogin()定义当需要用户登录时候,转到的登录页面。 configureGlobal(AuthenticationManagerBuilder auth)方法,在内存中创建了一个用户,该用户的名称为admin,密码为123456,用户角色为USER。

自定义密码解析

public class MyPasswordEncoder implements PasswordEncoder {
    @Override
    public String encode(CharSequence charSequence) {
        //MD5Util.encode((String) charSequence);
        System.out.println(charSequence.toString());
        return null;
    }

    @Override
    public boolean matches(CharSequence charSequence, String s) {
        System.out.println(charSequence);
        System.out.println(s);
        return  s.equals(charSequence.toString());;
    }
}

指定了密码的加密方式(5.0 版本强制要求设置),因为我们数据库是明文存储的,所以明文返回即可

自定义UserDetailsService实现类

@Service
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private SysUserDao sysUserDao;

    /**
     * 授权的时候是对角色授权,认证的时候应该基于资源,而不是角色,因为资源是不变的,而用户的角色是会变的
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUserEntity userEntity = sysUserDao.findByUserName(username);
        if (null == userEntity) {
            throw new UsernameNotFoundException(username);
        }
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        List<SysRoleEntity> roleList = userEntity.getRoleList();
        if(roleList == null || roleList.size() == 0){
            return new User(userEntity.getUserName(), userEntity.getPassword(), authorities);
        }
        for (SysRoleEntity role : roleList) {
            List<SysPermissionEntity> permList = role.getPermissionEntityList();
            if(permList == null){
                continue;
            }
            for(SysPermissionEntity permission : permList){
                //添加用户的权限
                authorities.add(new SimpleGrantedAuthority(permission.getCode()));
            }
        }
        return new User(userEntity.getUserName(), userEntity.getPassword(), authorities);
    }
}

需要重写 loadUserByUsername 方法,参数是用户输入的用户名。返回值是UserDetails,这是一个接口,一般使用它的子类org.springframework.security.core.userdetails.User,它有三个参数,分别是用户名、密码和权限集。

自定义对 hasPermission()

@Component
public class CustomPermissionEvaluator implements PermissionEvaluator {
    @Override
    public boolean hasPermission(Authentication authentication, Object targetUrl, Object targetPermission) {
        // 获得loadUserByUsername()方法的结果
        User user = (User)authentication.getPrincipal();
        // 获得loadUserByUsername()中注入的角色
        Collection<GrantedAuthority> authorities = user.getAuthorities();
        for(GrantedAuthority authority : authorities){
            if(authority.getAuthority().equals(targetPermission)){
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable serializable, String s, Object o) {
        return false;
    }
}
@RestController
public class PermissionController {

    @RequestMapping("/perm")
    @PreAuthorize("hasPermission('/perm','perm')")
    public String perm(){
        return "success";
    }
}

@PreAuthorize("hasPermission('/perm','perm')")是关键,参数1指明了访问该接口需要的url,参数2指明了访问该接口需要的权限

自定义Filter

public class MyAuthenticationFilter  extends AbstractAuthenticationProcessingFilter {

    public MyAuthenticationFilter(String defaultFilterProcessesUrl) {
        super(defaultFilterProcessesUrl);
    }


    @Override
    public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException {
        return null;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        String userName = (String) req.getSession().getAttribute("username");
        if("test".equals(userName)){
            super.unsuccessfulAuthentication(req, res,new InsufficientAuthenticationException("输入的验证码不正确"));
        }
       // super.unsuccessfulAuthentication(req, res,new InsufficientAuthenticationException("输入的验证码不正确"));
        chain.doFilter(request, response);
    }
}

实体类

@Data
@Entity
@Table(name = "sys_user")
public class SysUserEntity {

    @Id
    @GeneratedValue
    @Column(name = "user_id")
    private Long userId;

    @Column(nullable = false,unique = true, length =  50)
    private String userName;

    @Column(nullable = false, length =  200)
    private String password;

    @ManyToMany(cascade = {CascadeType.ALL},fetch = FetchType.EAGER)
    @JoinTable(name="sys_user_role_map",joinColumns={@JoinColumn(name="user_id")},inverseJoinColumns={@JoinColumn(name="role_id")})
    List<SysRoleEntity> roleList;
}
@Data
@Entity
@Table(name = "sys_role")
public class SysRoleEntity {

    @Id
    @Column(name = "role_id")
    private Long roleId;

    @Column(nullable = false, length =  200)
    private String roleName;

    @ManyToMany(cascade = {CascadeType.ALL},fetch = FetchType.EAGER)
    @JoinTable(name="sys_role_permission_map",joinColumns={@JoinColumn(name="role_id")},inverseJoinColumns={@JoinColumn(name="perm_id")})
    List<SysPermissionEntity> permissionEntityList;

}
@Data
@Entity
@Table(name = "sys_permission")
public class SysPermissionEntity {

    @Id
    @Column(name = "perm_id")
    private Long permId;

    @Column(length = 30)
    private String code;
}

DAO类

@Repository
public interface SysUserDao  extends JpaRepository<SysUserEntity, Long> {
     SysUserEntity findByUserName(String userName);
}

运行程序

在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot集成Spring Security相对简单。以下是集成Spring Security的步骤: 步骤1:添加依赖 在项目的pom.xml文件中添加spring-boot-starter-security依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> ``` 步骤2:创建Spring Security配置类 创建一个继承自WebSecurityConfigurerAdapter的Java类,用于配置Spring Security。你可以通过覆盖configure方法来自定义配置。 ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/public").permitAll() // 允许公共访问的URL .anyRequest().authenticated() // 其他URL需要身份验证 .and() .formLogin() .loginPage("/login") // 登录页面的URL路径 .permitAll() .and() .logout() .logoutUrl("/logout") // 退出登录的URL路径 .permitAll(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("user").password("{noop}password").roles("USER"); // 在内存中创建一个用户 } } ``` 步骤3:配置登录和注销页面 在上面的配置类中,我们指定了登录页面和注销URL的路径。你需要创建这些页面并在应用程序中实现对应的逻辑。 步骤4:启用Spring Security 在应用程序的启动类上添加@EnableWebSecurity注解,以启用Spring Security。 ```java @SpringBootApplication @EnableWebSecurity public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } } ``` 以上就是将Spring Security集成Spring Boot应用程序的基本步骤。你可以根据具体需求进一步定制和扩展配置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值