0710~SpringSecurity

SpringSecurity:概念:是一个声明式的提供安全访问控制的操作的安全框架;

学习有五个阶段:

小试牛刀:springsecuirtyDemo

登堂入室:用用户名拿到用户信息,根据用户信息找到用户对应的权限字符串;

游刃有余:授权方式认证;两种方式(1.web配置 2.注解方法配置);

登峰造极:认证结果处理,授权结果处理;

走火入魔:remberer_me;

 小试牛刀:springsecuirtyDemo

思路步骤:

1.导入依赖,配置类;

2.设置登录成功后返回的路径;

3.网页直接访问login即可;

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
    </parent>

    <dependencies>
        <!--SpringSecurity依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <!--web基础依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--测试依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.73</version>
        </dependency>

        <!--junit测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>
        <!-- mysql数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.20</version>
        </dependency>
    </dependencies>

@RestController
public class AuthController {

    //登录成功后重定向地址
    @PostMapping("/loginSuccess")
    public String loginSuccess(){
        return "登录成功";
    }
}

 

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    //提供用户信息,这里没有从数据库查询用户信息,在内存中模拟
    @Bean
    public UserDetailsService userDetailsService(){
        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
        inMemoryUserDetailsManager.createUser(User.withUsername("zs").password("123456").authorities("admin").build());
        return inMemoryUserDetailsManager;
    }

    //密码编码器:不加密
    @Bean
    public PasswordEncoder passwordEncoder(){
        return NoOpPasswordEncoder.getInstance();
    }

    //授权规则配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()                                //授权配置
                .antMatchers("/login").permitAll()  //登录路径放行
                .anyRequest().authenticated()                   //其他路径都要认证之后才能访问
                .and().formLogin()                              //允许表单登录
                .successForwardUrl("/loginSuccess")             // 设置登陆成功页
                .and().logout().permitAll()                    //登出路径放行 /logout
                .and().csrf().disable();                        //关闭跨域伪造检查
    }
}

 

登堂入室:用用户名拿到用户信息,根据用户信息找到用户对应的权限字符串;

思路步骤:

1.连接数据库使用真实的用户名密码,删除demo里的假数据;

2.配置类实现

UserDetailsService
接口,重写里面的hander方法;

3.根据用户名拿到用户对象,根据用户对象再拿到权限字符串;

4.把权限字符串给springsecurity管理;

 

@Component
@Slf4j
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private PermissionMapper permissionMapper;

    //通过用户名拿到用户信息,还有权限字符串
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        if(!StringUtils.hasLength(username)){
            throw new MyException("用户名不可为空");
        }
        User user = userMapper.selectByUsername(username);
        if(user==null){
            throw new MyException("该用户名不存在");
        }
        //通过用户id拿到权限集合
        List<Permission> permissions = permissionMapper.selectPermissionsByUserId(user.getId());
        ArrayList<GrantedAuthority> list = new ArrayList<>();
        for(int i=0;i<permissions.size();i++){
            Permission permission = permissions.get(i);
            SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(permission.getExpression());
            log.info("用户,{},可用的权限有,{}",user.getUsername(),simpleGrantedAuthority);
            list.add(simpleGrantedAuthority);
        }

        org.springframework.security.core.userdetails.User userDetails = new org.springframework.security.core.userdetails.User(user.getUsername(),user.getPassword(),list);

        return userDetails;
    }
}

 游刃有余:授权方式认证;两种方式(1.web配置 2.注解方法配置);

使用web配置,配置类即可,告诉SpringSecurity容器可以可以使用哪些权限;

  @Override
    protected void configure(HttpSecurity http) throws Exception {
        //先查出所有权限;
        //根据权限 找到权限字符串和资源路径
        //List<Permission> permissions = permissionMapper.selectList(null);
        //for (Permission permission : permissions) {
        //    http.authorizeRequests()
        //            .antMatchers(permission.getResource())
        //            .hasAnyAuthority(permission.getExpression());
        //    log.info("用户授权的权限有,{}",permission.getExpression());
        //}

 2.注解方法配置

1.再配置类上加注解@EnableGlobalMethodSecurity(prePostEnabled = true)

2.再需要验证的方法上加上注解 @PreAuthorize("hasAuthority('dept:list')")

@RequestMapping("/list")
    @PreAuthorize("hasAuthority('dept:list')")
    public String list(){
        return "查询部门列表成功";
    }
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

登峰造极:认证结果处理,授权结果处理; 

认证结果分两种,认证失败和认证成功;

思路步骤:配置类失败实现AuthenticationFailureHandler接口;

                         成功实现AuthenticationSuccessHandler接口;

/**  认证失败的配置类
 * @author liuliang
 * @date 2022-07-10 19:19
 */
@Component
public class MyAuthenticationSuccessHandler implements AuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest request,
                                        HttpServletResponse response,
                                        AuthenticationException e) throws IOException, ServletException {

        response.setContentType("application/json;charset=utf-8");
        response.getWriter().print(JSONObject.toJSONString(JSONResult.error("认证失败,请登录")));


    }

}

 

/** 认证成功的类
 * @author liuliang
 * @date 2022-07-10 19:40
 */
@Component
public class MyAuthenticationSuccessHandlerSuccess implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
                                        HttpServletResponse response,
                                        Authentication authentication) throws IOException, ServletException {
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().print(JSONObject.toJSONString(JSONResult.success("恭喜你登录成功!")));

    }
}

 授权结果处理; 

1.如若授权成功则直接访问;

2.如果没有权限则返回失败结果集;

3.如果未登录访问则直接返回匿名用户不可登录;

/**
 * @author liuliang  授权失败的访问类
 * @date 2022-07-10 19:50
 */
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request,
                       HttpServletResponse response,
                       AccessDeniedException e) throws IOException, ServletException {
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().print(JSONObject.toJSONString(JSONResult.error("您没有此权限!!!")));

    }
}
/**匿名用户访问类
 * @author liuliang
 * @date 2022-07-10 19:50
 */
@Component
public class MyAccessDeniedHandlerPoint implements AuthenticationEntryPoint {


    @Override
    public void commence(HttpServletRequest request,
                         HttpServletResponse response,
                         AuthenticationException e) throws IOException, ServletException {
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().print(JSONObject.toJSONString(JSONResult.error("您是匿名用户,无法访问此路径!")));
    }
}

 走过入魔:remember_me;

页面设置记住我,可以把用户信息存入cookie,下次则不用登录即可访问接口;

思路步骤:

1.再配置类里面设置jdbctoken仓库;

2.在实现方法里面实现关联即可;

//开始配置记住我功能代码
    @Autowired
    private DataSource dataSource;

    @Bean
    public JdbcTokenRepositoryImpl jdbcTokenRepository(){
        JdbcTokenRepositoryImpl repository = new JdbcTokenRepositoryImpl();
        repository.setDataSource(dataSource);
        //repository.setCreateTableOnStartup(true);//启动时会自动创建表
        return repository;
    }

 

 http.rememberMe()
                .tokenRepository(jdbcTokenRepository())
                .tokenValiditySeconds(60*60)
                .userDetailsService(myUserDetailsService);

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值