項目2---十次方項目開發---後臺--鑑權和JWT---06

第一步:引入springSecurity。

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

默認的配置是攔截所有的路徑。

第二步:寫配置類

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     * authorizeRequests:所有security全註解配置實現的開端。表示開始說明需要的權限
     * 需要的權限分兩部分,第一部分是攔截的路徑,第二部分訪問路徑需要的權限
     * antMatchers:表示攔截路徑,permitAll表示任何權限都可以使用,直接放行所有
     * anyRequest():任何的請求,authenticated():認證後才能訪問
     * .and().csrf().disable():固定寫法,表示使csrf攔截失效
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/**").permitAll()
                .anyRequest().authenticated()
                .and().csrf().disable();
    }
}

這個適配器實現了一些空的方法。這段可以作爲模板貼上去的。

-------------------------------------------------------------------01-----------------------------------------02----------------03-----------------------------------

springboot是把web.xml拿掉的。

web.xml是初始化的,現在這個替代了。

---------------------------------------------------------------------------04-----------------------------------------------------------------------

加密的網址:https://www.jianshu.com/p/89c4c476e189

引入加密算法:

第一步:

@SpringBootApplication
public class UserApplication {

	public static void main(String[] args) {
		SpringApplication.run(UserApplication.class, args);
	}

	@Bean
	public IdWorker idWorkker(){
		return new IdWorker(1, 1);
	}

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

第二步:注入和使用,對密碼進行加密存入到數據庫。

public void add(Admin admin) {
		admin.setId( idWorker.nextId()+"" ); //雪花分佈式ID生成器
		admin.setPassword(encoder.encode(admin.getPassword()));//密碼加密
		adminDao.save(admin);
	}

第三步:測試

---------------------------------------------------------------------------05-----------------------------------------------------------------------

寫登陸:

第一步:

	public Admin login(Admin admin) {
		//先根據用戶名查詢對象.
		Admin admin_login = adminDao.findByLoginname(admin.getLoginname());
		//拿數據庫中的密碼和用戶輸入的密碼匹配是否相同
		if(admin_login!=null&&encoder.matches(admin.getPassword(),admin_login.getPassword())){
			//保證數據庫中的密碼和用戶輸入的密碼是一致的
			//登錄成功
			return admin_login;
		}
		//登錄失敗
		return null;
	}

知識點:

@RequestBody:可以轉爲對象也可以轉爲map。

第二步:寫controller

-----------------------------------------------------------------------------06----------------------------------------------------------------------------

用戶的註冊登陸的改造:

第一步:加密關鍵代碼

/**
	 * 增加
	 * @param user
	 */
	public void add(User user) {
		user.setId( idWorker.nextId()+"" );
		//密碼加密
		user.setPassword(encoder.encode(user.getPassword()));
		user.setFollowcount(0);//關注數
		user.setFanscount(0);//粉絲數
		user.setOnline(0L);//在線時長//
		user.setRegdate(new Date());//註冊日期
		user.setUpdatedate(new Date());//更新日期
		user.setLastdate(new Date());//最後登陸日期
		userDao.save(user);
	}

第二步:登陸關鍵代碼

public User login(String mobile,String password) {
		User user = userDao.findByMobile(mobile);
		if(user!=null && encoder.matches(password,user.getPassword())){
			return user;
		}
		return null;
	}

---------------------------------------------------------------------------07-----------------------------------------------------------------------

常見的認證機制:

1.每次都帶上用戶名和密碼,無狀態的。

2.CooKie Auth:登陸的信息在瀏覽器存在cookie,服務器存在session中。安卓ios什麼的不方便。手機端現在越來越流行了。

3.OAuth:

4.Token Auth:

服務端是不存的用JWT算法。到時候我解密就可以了。

這個token的生成策略我們用的是JWT。

---------------------------------------------------------------------------08-----------------------------------------------------------------------

token的優點:

---------------------------------------------------------------------------09-----------------------------------------------------------------------

JWT生成tokrn的規則:

頭部,載荷,簽名。

頭部:

載荷:

簽名:對頭部和載荷進行加密。

最後一點JWT是後臺簽發的。三部分組成。

---------------------------------------------------------------------------10-----------------------------------------------------------------------

JJWT:

第一步:導入座標在common模塊注意是在common模塊裏面。

  <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

第二步:

 List<Object> roles=new ArrayList<>();
        roles.add("role1");
        roles.add("role2");
        JwtBuilder jwtBuilder = Jwts.builder()
                //用戶的id用戶名
                .setId("666") .setSubject("小馬")
                .setIssuedAt(new Date())//何時登陸的
                .signWith(SignatureAlgorithm.HS256,"wmlw")//頭部信息  後面的是加的鹽
                .setExpiration(new Date(new Date().getTime()+60000))
                .claim("roles",roles);
        System.out.println(jwtBuilder.compact());

這個set是按照這個標準set的:

----------------------------------------------------------------------------------11---------------------------------------------------------------------------------

解析JWT:

public static void main(String[] args) {
        //Claims裏面就是key和value
        Claims claims = Jwts.parser().setSigningKey("wmlw")
                .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI2NjYiLCJzdWIiOiLlsI_pqawiLCJpYXQiOjE1ODAzNjA5NzksImV4cCI6MTU4MDM2MTAzOSwicm9sZXNBZGQiOlsicm9sZTEiLCJyb2xlMiJdfQ.Lx9C8olEcY29NHSx90Q0aifA1JjwzwyyKpWkadzk2eI")
                .getBody();
        System.out.println("用戶id"+claims.getId());
        System.out.println("用戶名"+claims.getSubject());
        System.out.println("登錄時間"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(claims.getIssuedAt()));
        System.out.println("過期時間"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(claims.getExpiration()));
        System.out.println("角色"+claims.get("rolesAdd"));
    }

---------------------------------------------------------------------------12-----------------------------------------------------------------------

token的過期時間:

同上。

---------------------------------------------------------------------------13-----------------------------------------------------------------------

添加自定義的鍵值對:

---------------------------------------------------------------------------14-----------------------------------------------------------------------

token工具類:

第一步:拷貝JwtUtils:

注意下這個微服務的配置文件是引用它的微服務的配置文件讀取的。沒毛病。

第二步:

必傳的信息:id,

---------------------------------------------------------------------------15-----------------------------------------------------------------------

admin登陸生成token:

第一步:我們寫加鹽的yml注意在哪個模塊裏面。

第二步:在啓動類加Jwt工具。

第三步:寫代碼

用戶 角色 權限 都是多對多

    @PostMapping("/login")
    public Result login(@RequestBody Admin admin) {
        Admin adminLogin = adminService.login(admin);
        if (adminLogin == null) {
            return new Result(false, StatusCode.ERROR, "登錄失敗");
        }
        //是的前後端可以通話的操作。採用JWT操作
        //生成令牌
//        List<Object> roles = new ArrayList<>();
//		roles.add("role1");
//		roles.add("role2");
        String token = jwtUtil.createJWT(adminLogin.getId(), adminLogin.getLoginname(), "admin");
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("role", "admin");
        return new Result(true, StatusCode.OK, "登錄成功", map);
//        return new Result(true, StatusCode.OK, "登錄成功", "登陸憑證");

    }

測試登陸:

---------------------------------------------------------------------------16-----------------------------------------------------------------------

我們假設一個場景:刪除的功能。我們要把token放在請求頭裏面。

第一步:request是一次請求,拿到request才能拿到請求頭。

測試:

先登陸:

請求:

--------------------------------------------------------------------------17----------18-------------------------------------------------------------

用攔截器寫:

其實也可以用springSecurity。

jdk1.8的好處:

第一步寫攔截器:

攔截器都放行,不管是什麼,在請求的request寫入角色。

第二步:寫配置configuration

相當於配置xml。

-----------------------------------------------------------------------19------20---------------------------------------------------------------- 

攔截器的驗證測試:

第一步:改造userService

   public void deleteById(String id) {
//        String header = request.getHeader("Authorization");
//        if (header == null || header.equals("")) {
//            throw new RuntimeException("權限不足!");
//        }
//        if (!header.startsWith("Bearer ")) {
//            throw new RuntimeException("權限不足");
//        }
//        //得到token
//        String token = header.substring(7);
//        try {
//            Claims claims = jwtUtil.parseJWT(token);
//            String roles = (String) claims.get("roles");
//            if (roles == null && !"admin".equals(roles)) {
//                throw new RuntimeException("權限不足");
//            }
//        } catch (Exception e) {
//            throw new RuntimeException("權限不足");
//        }
        String token=(String)request.getAttribute("claims_admin");
        if(token==null || "".equals(token)){
            throw new RuntimeException("權限不足");
        }
        userDao.deleteById(id);
    }

測試:略。

--------------------------------------------------21---------------------------------------------

問答的token問題。

登陸才能問問題。

第一步:在UserService。

	@PostMapping("/login")
	public Result login(@RequestBody User user){
		user=userService.login(user.getMobile(),user.getPassword());
		if(user==null){
			return new Result(false,StatusCode.ERROR,"登錄失敗");
		}
		String token = jwtUtil.createJWT(user.getId(), user.getMobile(), "user");
		Map<String,Object> map =new HashMap<>();
		map.put("token",token);
		map.put("roles","user");
		return new Result(true,StatusCode.OK,"登錄成功",map);
//		return new Result(true,StatusCode.OK,"登錄成功","登陸成功");
	}

第二步:在問答裏面驗證

yml導入配置:

第三步:將過濾器導入

第四步:

/**
	 * 增加
	 * @param problem
	 */
	@RequestMapping(method=RequestMethod.POST)
	public Result add(@RequestBody Problem problem  ){
		String token=(String)request.getAttribute("claims_user");
		if(token ==null || "".equals(token)){
			return new Result(false,StatusCode.ACCESSERROR,"權限不足");
		}
		problemService.add(problem);
		return new Result(true,StatusCode.OK,"增加成功");
	}

--------------------------------------------------22---------------------------------------------

發佈了304 篇原創文章 · 獲贊 11 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章