01->SpringSecurity认证框架的自定义配置(微服务第一步)

目录

1. 依赖

2. jackson(spring boot包下的)

3. yml基本不写  使用SecurityConfig

4. 自定义登录逻辑    -> 4.1 在配置类中@Bean

--> 自定义登录(连接数据库)模拟数据库

authentication对象

权限控制​

没认证失败处理器 401

认证权限失败处理器  403

 ------------------------------------

引出cookie和session  会话技术


1. 依赖

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

2. jackson(spring boot包下的)

//jackson  将map对象转换为json对象 spring-boot-starter-web
//pw.println("{\"status\":200,\"msg\":\"ok\"}");
package com.cy.jt.security.config.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

public class JsonAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
                                        HttpServletResponse response,
                                        Authentication authentication)
            throws IOException, ServletException {
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=utf-8");
        PrintWriter pw= response.getWriter();
        Map<String,Object> map=new HashMap<>();
        map.put("state", 200);
        map.put("msg", "Login ok");
        //jackson  将map对象转换为json对象 spring-boot-starter-web
        //pw.println("{\"status\":200,\"msg\":\"ok\"}");
        String jsonStr = new ObjectMapper().writeValueAsString(map);
        pw.println(jsonStr);
        pw.flush();
    }
}

3. yml基本不写  使用SecurityConfig

4. 自定义登录逻辑
    -> 4.1 在配置类中
@Bean

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

 配置类信息

package com.cy.jt.security.config;

import com.cy.jt.security.config.handler.JsonAuthenticationSuccessHandler;
import com.cy.jt.security.config.handler.RedirectAuthenticationSuccessHandler;
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.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

//配置类 启动就会优先加载  @configuration  通常会对第三方资源进行整合

/**
 * 资源放行  还是在配置类中添加放行条件 和成功失败返回情况
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 对http请求的安全控制进行配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();//1.关闭跨域攻击

        //自定义登录页面
        http.formLogin()
                .loginPage("/login.html")//2.设置登录url(静态页面)
                .loginProcessingUrl("/login")//地址对应的处理器 与页面action相同
//                .usernameParameter("username")
//                .passwordParameter("password")  与前端不相同就添加属性
                //.successForwardUrl("/index.html");//get请求  会405的
                //.successForwardUrl("/index");//get请求  写个controller接收可以获取到请求的用户名
               // .defaultSuccessUrl("/index.html")//默认请求成功路径 默认转发
                .failureUrl("https://www.baidu.com") //默认....error 跳回原页面

                .successHandler(
                        //new RedirectAuthenticationSuccessHandler("/index.html"));
                        new JsonAuthenticationSuccessHandler());


        //3. 放行登录url  不用认证,其他认证
        http.authorizeRequests()
                .antMatchers("/login.html","/images/**")
                .permitAll()//允许访问上面的
                .anyRequest().authenticated();//其他任何请求都需要认证
    }

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


}

--> 自定义登录(连接数据库)模拟数据库

package com.cy.jt.security.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
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.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 自定义登录逻辑  UserDetailsService需要实现
 */
@Service
public class UserDetailServiceImpl implements UserDetailsService {

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;
//分配权限方式是 角色  使用 ROLE_ 做前缀

    @Override
    public UserDetails loadUserByUsername(String username)
                                throws UsernameNotFoundException {
       //userMapper.selectUSerByUsername(username)

        if(!"pzy".equals(username))
            throw new UsernameNotFoundException("user not exists");
//从数据库查看权限信息
        List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList(
                "ROLE_jinpai,ROLE_tongpai,sys:res:retrieve,sys:res:create"
        );

        String  encodePwd  =passwordEncoder.encode("123456");
        //import org.springframework.security.core.userdetails.User;
        User user=new User(username, encodePwd, authorities);

        return user;
    }
}
------------------
登录成功处理器  AuthenticationSuccessHandler 
登录失败处理器  AuthenticationFailureHandler

需要继承的   然后重新编写配置类SecurityConfig

.failureHandler (new AuthenticationFailureHandler)
.successHandler (new AuthenticationSuccessHandler)

-----------------------------------------

authentication对象

User principal =(User) authentication.getPrincipal();//继承userDetails


System.out.println( principal.getUsername());//获取权限用户名
System.out.println(principal.getPassword());
System.out.println(principal.getAuthorities());

Object credentials = authentication.getCredentials();//获取密码
System.out.println(principal);
System.out.println(credentials);

01->SpringSecurity认证框架的自定义配置(微服务第一步)

 01->SpringSecurity认证框架的自定义配置(微服务第一步)

 -------------------------------------------------------

权限控制01->SpringSecurity认证框架的自定义配置(微服务第一步)

--------------> 最开始 启动类家伙加上@EnableGlobalMethodSecurity(prePostEnabled = true)

在每个方法上添加

//@PreAuthorize("hasRole('normal')")
@PreAuthorize("hasAuthority('sys:res:retrieve')")

403 没权限   401 没认证  通常报错信息

-------------------------

直接报错吧不好  需要自定义异常处理机制

没认证失败处理器 401

package com.cy.jt.security.config.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * 401认证异常
 * 假如用户没有认证 就去访问需要认证才能访问的资源 系统
 * 底层会抛出异常 AuthenticationException
 * 系统默认对此异常的处理方式是跳转到登录页面
 */
public class DefaultAuthenticationEntryPoint implements AuthenticationEntryPoint {
    /**
     *
     * @param request
     * @param response
     * @param authException
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void commence(HttpServletRequest request,
                         HttpServletResponse response,
                         AuthenticationException authException)
            throws IOException, ServletException {

        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=utf-8");
        PrintWriter pw = response.getWriter();
        Map<String,Object> map=new HashMap<>();
        map.put("status", HttpServletResponse.SC_UNAUTHORIZED);//403
        map.put("message", "请先认证后, 在登录重试!!!");

        String jsonStr = new ObjectMapper().writeValueAsString(map);
        pw.println(jsonStr);
        pw.flush();



    }
}

认证权限失败处理器  403

package com.cy.jt.security.config.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * 默认的用于处理访问被拒绝的异常处理器对象
 * denied 拒绝
 */
public class DefaultAccessDeniedException implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request,
                       HttpServletResponse response,
                       AccessDeniedException accessDeniedException)
            throws IOException, ServletException {
           // response.sendRedirect("https://www.baidu.com");


        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=utf-8");
        PrintWriter pw = response.getWriter();
        Map<String,Object> map=new HashMap<>();
        map.put("status", HttpServletResponse.SC_FORBIDDEN);//403
        map.put("message", "没有权限, 请升级权限!!!");

        String jsonStr = new ObjectMapper().writeValueAsString(map);
        pw.println(jsonStr);
        pw.flush();



    }
}


 ------------------------------------

引出cookie和session  会话技术

上一篇:Spring security中的注解


下一篇:Spring Security OAuth2学习记录(一)