springboot-security+笔记+day0817

Myconfig.java

package com.neuedu.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import javax.annotation.Resource;

@Configuration
public class MyConfig {
    @Bean
    BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    CorsFilter corsFilter(){
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.addAllowedOrigin("*");
        configuration.addAllowedMethod("*");
        configuration.addAllowedHeader("*");
        source.registerCorsConfiguration("/**",configuration);
         return new CorsFilter(source);
    }


    @Resource
    RedisTemplate redisTemplate;
    @Bean
    RedisTemplate<String,String> getRedisTemplate(){

        RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setValueSerializer(stringRedisSerializer);
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setHashValueSerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        return redisTemplate;
    }
}

JwtAuthentication.java

package com.neuedu.security;

import com.neuedu.pojo.UmsUser;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;

//和过滤器很像啊
//这个写好后方进入ioc容器
@Component
public class JWTAuthentication  extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {

        String jwt = httpServletRequest.getHeader("token");
      //  Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
//        if(headerNames.hasMoreElements()){
//            System.out.println(headerNames.nextElement());//host
//        }

        //System.out.println(httpServletRequest.getMethod()); //OPTIONS

        if(!"OPTIONS".equals(httpServletRequest.getMethod())){
            System.out.println(jwt);

            //解析出jwt ,拿到username

            //通过username 到 redis 中 查看 key是否存在


            //如果存在,  则从redis 中取出 user 对象, 和jwt 中进行密码校验


            //如果都对,则可以通过认证

        }
        //



//        //生产一个umsUser对象
//        UmsUser umsUser = new UmsUser();
//        umsUser.setUsername("admin");
//        umsUser.setPassword("1234");
//        UserDetails userDetails = new UmsUserDetails(umsUser);
//
//
//        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());
//        //有这句就表示有身份认证*********
//        SecurityContextHolder.getContext().setAuthentication(token);

        filterChain.doFilter(httpServletRequest,httpServletResponse);

    }
}

RestNoToken.java 自定义错误

package com.neuedu.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.neuedu.util.CommonResult;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class RestNoToken implements AuthenticationEntryPoint {

    @Resource
    ObjectMapper objectMapper;


    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        httpServletResponse.setHeader("Access-Control-Allow-Origin","*");
        httpServletResponse.setCharacterEncoding("utf-8");
        httpServletResponse.setContentType("text/html;charset=utf-8");

        httpServletResponse.getWriter().write(objectMapper.writeValueAsString( CommonResult.notoken()));
    }
}

SecurityConfig.java

package com.neuedu.security;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;

@Configuration
//如何配置spring-security呢?首先建立一个类,放进ioc容器,
// 并且必须继承WebSecurityConfigurerAdapter
public class SecurityConfig  extends WebSecurityConfigurerAdapter {


    @Resource
    RestNoToken restNoToken;



    @Resource
    JWTAuthentication jwtAuthentication;

    //必须重写configurer方法

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry
                registry = http.authorizeRequests();

        //所有的option都通过
        registry.antMatchers(HttpMethod.OPTIONS)
                .permitAll();

        //这句话的意思是除了/index不需要身份验证,其余都需要身份验证,其中antMatchers里面
        //的参数可以写多个,配置不用认证的地址
        registry.antMatchers(HttpMethod.POST,"/ums-user/login")
                .permitAll()
                .antMatchers("/index")
                .permitAll()
                .anyRequest()
                .authenticated();

        //前后分离的话就是把下面的配置一下,关闭session
        registry.and()
                .csrf()
                .disable()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        //自定义没有认证返回什么东西,如果自定义没有权限的返回内容,就必须自己写个类
        //自定义没有认证返回的内容
        registry.and()
                .exceptionHandling()
                .authenticationEntryPoint(restNoToken);

        //下一步是怎么才能让他有认证
        //如果自定义认证方式,必须自己写一个类,
        // 实际上是一个过滤器,必须继承一个父类
        //自定义验证
        registry.and()
                .addFilterBefore(jwtAuthentication, UsernamePasswordAuthenticationFilter.class);






    }
}

UmsUserDetails.java

package com.neuedu.security;

import com.neuedu.pojo.UmsUser;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;


@Data
@NoArgsConstructor
@AllArgsConstructor

public class UmsUserDetails implements UserDetails {

    private UmsUser umsUser;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    //用户信息
    @Override
    public String getPassword() {
        return umsUser.getPassword();
    }

    @Override
    public String getUsername() {
        return umsUser.getUsername();
    }

    //这几个是  是否已经失效了
    @Override
    public boolean isAccountNonExpired() {
        return false;
    }

    @Override
    public boolean isAccountNonLocked() {
        return false;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return false;
    }

    @Override
    public boolean isEnabled() {
        return false;
    }
}

IRedisService.java

package com.neuedu.service;

public interface IRedisService {
    void set(String key,String value, long time);
    String get(String key);
    boolean haskey(String key);
    boolean expire(String key ,long time);
}

RedisServiceImpl.java

package com.neuedu.service.impl;

import com.neuedu.service.IRedisService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Service
public class RedisServiceImpl implements IRedisService {

    @Resource
    RedisTemplate<String,String> redisTemplate;

    @Override
    public void set(String key, String value, long time) {
        redisTemplate.opsForValue().set(key,value,time, TimeUnit.SECONDS);
    }

    @Override
    public String get(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    @Override
    public boolean haskey(String key) {
        return  redisTemplate.hasKey(key);
    }

    @Override
    public boolean expire(String key, long time) {
        return redisTemplate.expire(key,time,TimeUnit.SECONDS);
    }
}

JWTUtil.java---json web token(令牌)

package com.neuedu.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.neuedu.pojo.UmsUser;

import java.time.ZoneOffset;

public class JWTUtil {
    public static final String KEY = "umsuser";
    public static String create(UmsUser user){
        String jwt = JWT.create()
                .withClaim("username",user.getUsername())
                .withClaim("password",user.getPassword())
                .withClaim("timestamp",user.getLastlogin().toInstant(ZoneOffset.of("+8")).toEpochMilli())
                .sign(Algorithm.HMAC256(KEY));
        return jwt;

    }


}

ResoultCode.java(封装结果的枚举类)

package com.neuedu.util;

import lombok.Getter;

@Getter
public enum  ResultCode {

    SUCCESS(200,"操作成功"),
    FAILED(500,"操作失败"),
    NOTOKEN(401,"未登录或者登陆已经超时"),
    NOPREMISS(403,"没有权限")
    ;


    private Integer code;
    private String message;

    ResultCode(Integer code, String message) {
        this.code = code;
        this.message = message;
    }
}



通用的封装结果 CommonResult.java

package com.neuedu.util;

import lombok.Getter;

@Getter
public class CommonResult {
    private Integer code;
    private String message;
    private Object obj;

    private CommonResult(Integer code, String message, Object obj) {
        this.code = code;
        this.message = message;
        this.obj = obj;
    }

    public static CommonResult success(Object obj)
    {
        return new CommonResult(ResultCode.SUCCESS.getCode(),ResultCode.SUCCESS.getMessage(),obj);
    }

    public static CommonResult failed()
    {
        return new CommonResult(ResultCode.FAILED.getCode(),ResultCode.FAILED.getMessage(),null);
    }


    public static CommonResult failed(String msg)
    {
        return new CommonResult(ResultCode.FAILED.getCode(),msg,null);
    }

    public static CommonResult notoken()
    {
        return new CommonResult(ResultCode.NOTOKEN.getCode(),ResultCode.NOTOKEN.getMessage(),null);
    }
    public static CommonResult nopremiss()
    {
        return new CommonResult(ResultCode.NOPREMISS.getCode(),ResultCode.NOPREMISS.getMessage(),null);
    }


}

Mytest.java---测试类

package test;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.neuedu.App;
import com.neuedu.pojo.UmsUser;
import com.neuedu.service.IUmsUserService;
import org.jasypt.encryption.StringEncryptor;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class Mytest {

    @Resource
    RedisTemplate redisTemplate;

    @Resource
    IUmsUserService iUmsUserService;

    @Resource
    StringEncryptor stringEncryptor;

    @Resource
    BCryptPasswordEncoder encoder;

    @Test
    public void handler(){
        UmsUser user = new UmsUser(
                "abc",
                "1234",
                LocalDateTime.now(),
                1
        );
        System.out.println(iUmsUserService.saveOrUpdate(user));
    }


    @Test
    public void handlerjasypt(){
        //System.out.println(stringEncryptor.encrypt("1234"));//XGHSdlg7WW4jMVKIBQ8u5Q==
        System.out.println(stringEncryptor.encrypt("root"));//HspPg+u2KikM9Yb2sUuB5A==
        // System.out.println(stringEncryptor.decrypt("XGHSdlg7WW4jMVKIBQ8u5Q=="));
    }

    @Test
    public void handlerList(){
        System.out.println(iUmsUserService.list());
    }


    @Test
    public  void test(){
        System.out.println(encoder.encode("1234"));
        //$2a$10$uCGgugvM8BQsyVuhEFmrKONlZEimz3VfYEgsz0funoLYuugSykRVq
    }


    @Test
    public void testredis(){
        //注入一个redistTemplate,然后配置一下要连接的服务器是哪个
        redisTemplate.opsForValue().set("a","abc",60, TimeUnit.SECONDS);
        System.out.println("保存完成");
    }

    public static void main(String[] args) {
//        String jwt = JWT.create()
//                .withClaim("username","admin")
//                .withClaim("password","1234")
//                .withClaim("a","abcd")
//                .sign(Algorithm.HMAC256("user"));
//
//        System.out.println(jwt);
        //eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhIjoiYWJjZCIsInBhc3N3b3JkIjoiMTIzNCIsInVzZXJuYW1lIjoiYWRtaW4ifQ.HGbHvWY9lcDVj1bVYSlsDM1APMGhqxOy11RtyrqKRKk
        //有他就被看做已经被认证过的东西了

        String jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6IiQyYSQxMCRjNUhyVDhFU3g5S3dUMUpibi5VRGIueXZoZFRpWHdncng3MzhhZXhlcEZkaUhPYktGT25odSIsInVzZXJuYW1lIjoiYWRtaW4iLCJ0aW1lc3RhbXAiOjE1OTc2NzU1ODg4NDJ9.lY-gdfSl-lLHCQ_VFm1hYiN9bD_HwpneyyJ1xcf23jE";
        DecodedJWT decode = JWT.decode(jwt);

        //拿到username后 是否 可以 根据username 到 redis中取出 value
        //redis中的key 是 umsuser-username,如果拿不到说明未登录或者超时,
        //如果能够拿到,就可以将redis中的value 反序列化 为 UmsUser对象
        // 反序列化结束后还要  对比 token 中 password和 time是否 UmsUser对象一致

        String username = decode.getClaim("username").asString();//damin
        String password = decode.getClaim("password").asString();//1234
        Long timestamp = decode.getClaim("timestamp").asLong();
        System.out.println(username+"---->"+password+"---->"+timestamp);

    }
}

UmsUserController.java

package com.neuedu.controller;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.neuedu.pojo.UmsUser;
import com.neuedu.service.IUmsUserService;
import com.neuedu.util.CommonResult;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

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

import javax.annotation.Resource;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author liuyong
 * @since 2020-08-14
 */
@RestController
@RequestMapping("/ums-user")
public class UmsUserController {

    @Resource
    IUmsUserService iUmsUserService;

    @PostMapping("/login")
    CommonResult login(UmsUser umsUser) throws JsonProcessingException {
       String  jwt = iUmsUserService.token(umsUser);
       if(jwt != null){
           return CommonResult.success(jwt);
       }
       else{
           return CommonResult.failed("用户名或密码错误");
       }
    }


}

本博客仅作为笔记方便记忆---请勿用作其他用途

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值