用戶登陸並返回token(springboot)

何爲token?【若是想直接看代碼能夠往下翻】

使用基於 Token 的身份驗證方法,在服務端不須要存儲用戶的登陸記錄。大概的流程是這樣的:
1. 客戶端使用用戶名跟密碼請求登陸
2. 服務端收到請求,去驗證用戶名與密碼
3. 驗證成功後,服務端會簽發一個 Token,再把這個 Token 發送給客戶端
4. 客戶端收到 Token 之後能夠把它存儲起來,好比放在 Cookie 裏
5. 客戶端每次向服務端請求資源的時候須要帶着服務端簽發的 Token
6. 服務端收到請求,而後去驗證客戶端請求裏面帶着的 Token,若是驗證成功,就向客戶端返回請求的數據

token優勢

支持跨域訪問: Cookie是不容許垮域訪問的,這一點對Token機制是不存在的,前提是傳輸的用戶認證信息通
過HTTP頭傳輸.
無狀態(也稱:服務端可擴展行):Token機制在服務端不須要存儲session信息,由於Token 自身包含了全部登
錄用戶的信息,只須要在客戶端的cookie或本地介質存儲狀態信息.
更適用CDN: 能夠經過內容分發網絡請求你服務端的全部資料(如:javascript,HTML,圖片等),而你的服
務端只要提供API便可.
去耦: 不須要綁定到一個特定的身份驗證方案。Token能夠在任何地方生成,只要在你的API被調用的時候,你
能夠進行Token生成調用便可.
更適用於移動應用: 當你的客戶端是一個原平生臺(iOS, Android,Windows 8等)時,Cookie是不被支持的
(你須要經過Cookie容器進行處理),這時採用Token認證機制就會簡單得多。
CSRF:由於再也不依賴於Cookie,因此你就不須要考慮對CSRF(跨站請求僞造)的防範。
性能: 一次網絡往返時間(經過數據庫查詢session信息)總比作一次HMACSHA256計算 的Token驗證和解析
要費時得多.
不須要爲登陸頁面作特殊處理: 若是你使用Protractor 作功能測試的時候,再也不須要爲登陸頁面作特殊處理.
基於標準化:你的API能夠採用標準化的 JSON Web Token (JWT). 這個標準已經存在多個後端庫(.NET, Ruby,
Java,Python, PHP)和多家公司的支持(如:Firebase,Google, Microsoft)javascript

如何建立token【我這裏用的是Jwt機制,有些公司用的是本身的生成方法哈】

(1)建立maven工程,引入依賴前端

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

(2)使用工具類JwtUtilsjava

 1 /**
 2  * @author: Mr.Yang
 3  * @create: 2020-02-13 21:19
 4  **/
 5 @Getter
 6 @Setter
 7 @ConfigurationProperties("jwt.config")
 8 public class JwtUtils {
 9     //簽名私鑰
10     private String key;
11     //簽名失效時間
12     private Long failureTime;
13 
14     /**
15      * 設置認證token
16      *
17      * @param id      用戶登陸ID
18      * @param subject 用戶登陸名
19      * @param map     其餘私有數據
20      * @return
21      */
22     public String createJwt(String id, String subject, Map<String, Object> map) {
23 
24         //一、設置失效時間啊
25         long now = System.currentTimeMillis();  //毫秒
26         long exp = now + failureTime;
27 
28         //二、建立JwtBuilder
29         JwtBuilder jwtBuilder = Jwts.builder().setId(id).setSubject(subject)
30                 .setIssuedAt(new Date())
31                 //設置簽名防止篡改
32                 .signWith(SignatureAlgorithm.HS256, key);
33 
34         //三、根據map設置claims
35         for (Map.Entry<String, Object> entry : map.entrySet()) {
36             jwtBuilder.claim(entry.getKey(), entry.getValue());
37         }
38         jwtBuilder.setExpiration(new Date(exp));
39 
40         //四、建立token
41         String token = jwtBuilder.compact();
42         return token;
43     }
44 
45     /**
46      * 解析token
47      *
48      * @param token
49      * @return
50      */
51     public Claims parseJwt(String token) {
52         Claims claims = Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody();
53         return claims;
54     }
55 
56 }
View Code

注意:web

@ConfigurationProperties("jwt.config")須要在配置文件中配置

(3)配置JwtUtils類
1     /**
2      * 配置jwt
3      *
4      * @return
5      */
6     @Bean
7     public JwtUtils jwtUtils() {
8         return new JwtUtils();
9     }

(4)編寫登陸方法數據庫

  一、編寫DAO層json

 1 /**
 2  * @author: Mr.Yang
 3  * @create: 2020-02-13 21:55
 4  **/
 5 @Repository
 6 public interface UserDAO {
 7 
 8     public User selectByMobileUser(String mobile);
 9 
10     public User selectByIdUser(String id);
11 }
View Code

  二、編寫xml寫Sql後端

 <select id="selectByMobileUser" parameterType="string" resultMap="userMap">
        select *
        from bs_user
        where mobile = #{mobile}
    </select>
View Code

  三、編寫service層跨域

 /**
     * 根據mobile查詢用戶
     *
     * @param mobile
     * @return
     */
    public User selectByMobile(String mobile) {
        return userDAO.selectByMobileUser(mobile);
    }
View Code

  四、編寫controller層cookie

 1  /**
 2      * 用戶登陸
 3      * 1.經過service根據mobile查詢用戶
 4      * 2.比較password
 5      * 3.生成jwt信息
 6      *
 7      * @param loginMap
 8      * @return
 9      * @requestBody把請求數據封裝(前端以json方式傳)
10      */
11     @RequestMapping(value = "/login", method = RequestMethod.POST)
12     public Result login(@RequestBody Map<String, String> loginMap) {
13         String mobile = loginMap.get("mobile");
14         String password = loginMap.get("password");
15         User user = userService.selectByMobile(mobile);
16         //登陸失敗
17         if (user == null || !user.getPassword().equals(password)) {
18             //既可使用拋異常,也可以使用直接返回錯誤碼(推薦)
19             return new Result(ResultCode.MOBILEORPASSWORDERROR);
20         } else {
21             //其餘數據以map集合存放在token中
22             Map<String, Object> dataMap = new HashMap<>();
23             dataMap.put("companyId", user.getCompanyId());
24             dataMap.put("companyName", user.getCompanyName());
25             //生成token並存入數據返回
26             String token = jwtUtils.createJwt(user.getId(), user.getUsername(), dataMap);
27             return new Result(Result.SUCCESS(), token);
28         }
29     }
View Code

  五、測試網絡

data就是返回的token,裏面存有用戶ID,用戶姓名及以map形式存入的數據(這裏主要看前端須要什麼就存什麼)


(6)用戶登陸成功以後,獲取用戶信息

 1  /**
 2      * 用戶登陸成功以後,獲取用戶信息
 3      * 1.獲取用戶id
 4      * 2.根據用戶id查詢用戶
 5      * 3.構建返回值對象
 6      * 4.響應
 7      *
 8      * @param request
 9      * @return
10      * @throws Exception
11      */
12     @RequestMapping(value = "/profile", method = RequestMethod.POST)
13     public Result profile(HttpServletRequest request) throws PendingException, Exception {
14 
15         /**
16          * 從請求頭信息中獲取token數據
17          *   1.獲取請求頭信息:名稱=Authorization(先後端約定)
18          *   2.替換Bearer+空格
19          *   3.解析token
20          *   4.獲取clamis
21          */
22 
23 
24         //1.獲取請求頭信息:名稱=Authorization(先後端約定)
25         String authorization = request.getHeader("Authorization");
26         if (StringUtils.isEmpty(authorization)) {
27 //            throw new PendingException(ResCode.UNAUTHENTICATED);
28             //系統未捕捉到請求頭信息
29             throw new CommonException(ResultCode.UNAUTHENTICATED);
30         }
31         //2.替換Bearer+空格
32         String token = authorization.replace("Bearer ", "");
33 
34         //3.解析token
35         Claims claims = jwtUtils.parseJwt(token);
36         //4.獲取clamis
37         String userId = claims.getId();
38 
39         //  String userId = "U01";
40         User user = userService.selectByIdUser(userId);
41 
42         /**此處只是爲了獲取token中的用戶數據,全部只簡單返回用戶對象,
43          * 工做則按實際要求多表查詢須要數據(根據用戶ID查詢權限)
44          */
45 
46         return new Result(ResultCode.SUCCESS, user);
47     }
View Code

(7)測試

相關文章
相關標籤/搜索