[Life] 100 điều có thể đáng suy nghĩ

1. Hãy nhớ kỹ: Ngủ là yếu tố quan trọng nhất của dưỡng sinh. Thời gian ngủ nên từ 21h đến 3h sáng. Vì thời gian này là mùa đông trong ngày, mùa đông chủ yếu là ẩn náu, mùa đông mà không ẩn náu thì mùa xuân, hạ sẽ không thể sinh trưởng, sang ngày hôm sau sẽ không có tinh thần.
2. Hết thảy các vị thuốc dùng để trị bệnh cho dù là Trung y hay là Tây y đều chỉ là trị phần ngọn, không trị tận gốc. Tại vì hết thảy bệnh tật đều bắt nguồn từ những nguyên nhân sai lầm mà sản sinh ra hậu quả sai lầm. Nguyên nhân sai lầm mà không trừ dứt, thì hậu quả sẽ không thể bỏ tận gốc. Nguồn gốc căn bản của sức khỏe là tại tâm. Hết thảy pháp từ tâm sinh ra. Tâm tịnh thân sẽ tịnh. Vì thế khi bị bệnh rồi, không được hướng ngoại cầu, phải dựa vào hệ thống phục hồi của bản thân để chữa trị bệnh của chính mình. Kỳ thực con người và động vật là giống nhau, bệnh của động vật đều là tự dựa vào bản thân mà tự hồi phục, và con người cũng có khả năng đó.
3. Quan niệm đúng đắn có tác dụng giúp người bệnh tiêu trừ bệnh tật tốt hơn nhiều so với sử dụng biệt dược đắt đỏ và phẫu thuật. Có được quan niệm đúng đắn, bạn sẽ có quyết định đúng đắn, bạn sẽ có hành vi đúng đắn, và bạn sẽ có thể phòng ngừa rất nhiều bệnh tật phát sinh.
4. Con người vốn hội tụ hết thảy trí huệ, tuyệt đối không phải là học từ trong sách vở, mà là từ tâm chân thành, tâm thanh tịnh của bản thân, từ trong [thiền] định mà sinh ra.
5. Trong giới sinh vật con người là linh thể có cấu tạo hoàn mỹ nhất, khi con người được sinh ra là đã có một cơ thể khỏe mạnh; sự điều chỉnh trạng thái khỏe mạnh của con người là dựa vào chính hệ thống điều tiết phục hồi của bản thân để hoàn thành, chứ không phải dựa vào nhân tố bên ngoài, các nhân tố bên ngoài chỉ có tác dụng phụ trợ.
6. Đại đa số hiện tượng bệnh tật của con người là hiện tượng biểu hiện khi cơ thể đang điều tiết, thanh lọc những thứ không tốt trong thân thể, là trạng thái biểu hiện ra khi cơ thể tự động điều tiết trở lại trạng thái cân bằng, vì thế chúng ta nên coi đó là hiện tượng sinh lý bình thường, chứ không nên coi đó là căn bệnh để tiêu diệt. Vì vậy khi con người bị bệnh, nhất định không nên có tâm thái oán trách và giận giữ, tâm lý phải ổn định, tâm định thì khí sẽ thuận, khí thuận thì máu sẽ thông, khi thuận huyết thông thì trăm bệnh đều sẽ tiêu tán.
7. Sức khỏe của con người không thể xa rời hai nhân tố: 1) Khí huyết đầy đủ; 2) Kinh mạch thông suốt ( bao gồm huyết quản và đường thông bài tiết những thứ cặn bã).
8. Khí huyết đầy đủ dựa vào: sự đầy đủ về thức ăn + dịch mật + bắt buộc trong khoảng thời gian (sau khi trời tối đến 1h40 sáng) có thể ngủ ngon giấc (thời gian này đại não hoàn toàn không làm việc, đều do thần kinh thực vật làm chủ đạo) + có thói quen sinh hoạt lành mạnh.
9. Kinh mạch thông suốt cần: Tâm thanh tịnh. Hết thảy thất tình lục dục đều có thể phá hoại tâm thanh tịnh, từ đó phá hoại sự lưu thông bình thường của kinh mạch.
10. Duy trì một cơ thể khỏe mạnh khỏe mạnh không chỉ cần “tăng thu” (gia tăng khí huyết), mà còn cần “tiết chi” (giảm thiểu sự hao tổn khí huyết).
11. Ăn uống quá độ không những không thể gia tăng khí huyết, mà còn trở thành những thứ cặn bã mang gánh nặng cho cơ thể, hơn nữa còn bị tiêu hao khí huyết để thanh lọc chúng đi. Lục phủ ngũ tạng là một xưởng gia công khí huyết, thức ăn là nguyên vật liệu, năng lực gia công là hữu hạn, còn thức ăn là vô hạn, cho nên số lượng thức ăn nhất thiết phải được khống chế.
12. Vận động thích hợp có thể giúp cho khí huyết lưu thông, nhưng đồng thời cũng tiêu hao đi khí huyết. Sự tuần hoàn của cơ thể tại vi mô chủ yếu dựa vào trạng thái lỏng và tĩnh mà đạt được, đây cũng là điều không thể thiếu cho một cơ thể khỏe mạnh.
13. Chất cặn bã trong cơ thể càng nhiều sẽ cần càng nhiều khí huyết để thanh lọc chúng, nhưng khi chất cặn bã nhiều lên và làm tắc huyết mạch sẽ làm giảm thiểu khí huyết, cái đó sẽ dẫn đến sự tuần hoàn ác tính, cũng chính là cơ lý khiến con người già yếu đi. Vì vậy nếu con người muốn khỏe mạnh không già yếu thì phải: 1) Giảm thiểu chất cặn bã trong cơ thể; 2) Tăng cường sự thông suốt của các đường kinh mạch; 3) Tăng cường khí huyết trong cơ thể.
14. Tin tưởng vào thuốc, tin tưởng vào số liệu kiểm tra, không bằng tin tưởng vào cảm giác của bản thân, tin tưởng rằng chính mình có đầy đủ năng lực để điều tiết. Nhưng trước hết bạn cần phải là người đắc đạo (trí huệ đã khai mở), mới có thể phân biệt được hết thảy những điều này.
15. Sự khỏe mạnh, khởi đầu từ việc điều hòa tâm tính. Vì sức khỏe của bạn, bạn hãy tu Phật. Tu Phật đạt được sự vui vẻ đó là sự hưởng thụ tối cao của đời người.
16. Đối với người có bệnh cũ mà nói, chỉ khi có khí huyết đầy đủ (một là thông qua phương pháp bổ sung khí huyết như đã giới thiệu ở đây, hai là thông qua việc đi tản bộ để đánh thông khí cơ), bệnh tình mới có thể hiển hiện ra. Vì thế người luyện công sau khi công phu đã đạt đến một trình độ nhất định đều xuất hiện một vài hiện tượng “bệnh”. Đến lúc đó phải vững vàng kiên định, tâm thần phải tĩnh lại và luyện nhiều tĩnh công hơn để gia tăng khí huyết của bản thân, để mau chóng vượt qua giai đoạn này.
17. Con người làm trái với quy luật dưỡng sinh, mặc dù không nhất định sẽ bị bệnh ngay lập tức, nhưng một khi đã hình thành thói quen, liền gia tăng nguy cơ mắc bệnh. Điều này giống với luật lệ giao thông, bạn vi phạm luật lệ giao thông, không nhất định sẽ xảy ra sự cố, nhưng tình trạng nguy hiểm là có thể thấy rất rõ ràng.
18. Tại sao con người nhất thiết phải duy trì trạng thái đói khát nhất định thì mới có lợi cho dưỡng sinh? Kỳ thực đây chính là sự vận dụng tuyệt diệu của chữ “Hư”. Đạo gia giảng, hư thì linh. Chính cái đó cùng với sự khiêm tốn khiến cho con người tiến bộ, giống như tự mãn khiến con người lạc hậu, vì thế con người nhất thiết phải thường xuyên duy trì trạng thái “hư linh”, mới có thể luôn luôn duy trì sự thanh tỉnh, duy trì sự khỏe mạnh.
19. Con người muốn khỏe mạnh, thì nhất thiết phải làm cho bên trong cơ thể có đầy đủ “khí” để “khí hóa” những thức ăn đi vào. Chỉ có như thế, thì bên trong thân thể bạn mới không tích tụ chất cặn bã, sẽ không có thức ăn thừa bị phóng thích và phân tán “hư hỏa” gây tổn hại các cơ quan nội tạng trong cơ thể bạn. Cái “hư hỏa” còn làm tổn hại “khí” của bạn. Vì thế, từ trên ý nghĩa đó có thể thấy, con người hiện đại bị bệnh, đại đa số là do ăn uống không điều độ mà thành.
20. “Nằm lâu hại khí”, “Ngồi lâu hại thịt”, “Nhàn hạ ắt khí ứ đọng”, lại dưỡng tĩnh quá độ, sẽ khiến công năng tiêu hóa của tì vị bị hạ thấp, chức năng của tạng phủ ì trệ, khí huyết lưu chuyển ứ tắc không thông thuận, lực đề kháng giảm, khả năng miễn dịch bị tổn hại, lượng đường, mỡ, axit uric, huyết áp tăng cao, dần dần lâu ngày, con người sẽ sinh bệnh, hơn nữa đa phần đều là thân thể yếu nhiều bệnh, ví dụ như cảm mạo thường xuyên, không muốn ăn, thần trí mỏi mệt, sốt ruột căng thẳng v.v…
21, Tục ngữ có câu “Linh cơ nhất động, kế thượng tâm lai” (nhạy bén hễ động, nảy ra sáng kiến). Chữ “cơ” nếu như có thể thực sự hiểu được thấu, thế thì ngộ tính của bạn được tính là đã khai mở rồi. Thầy giáo dạy người, bác sỹ trị bệnh, kỳ thực chính là đang chỉ ra cái “cơ” này của bạn, khiến cái “cơ” này của bạn khai mở. cái “cơ” này có lúc cũng gọi là “then chốt”. Đương nhiên cái “cơ” này khởi tác dụng là có điều kiện, cũng giống như khinh khí chỉ khi đạt đến nồng độ nhất định, thì gặp lửa mới có thể bùng cháy. Hãy nhớ kỹ, tác dụng của người khác đều là nhân tố bên ngoài, bản thân bạn mới thực sự là nguyên nhân bên trong.
22. Kỳ thực, rất nhiều sự phát hiện và phát minh chân chính, điều cần thiết [để sáng tạo ra chúng] không phải là cái gọi là hệ thống kiến thức trên sách vở; mà hoàn toàn ngược lại, một người chưa từng thông qua bất kể sự giáo dục nào một cách hệ thống, nhưng ngộ tính rất cao, là người có tư duy cởi mở, họ thường thực sự ngộ ra được chân tướng.
23. Con người tối kỵ nhất là loạn chữ, loạn tâm, khi đối ngoại có thể làm hỏng việc, đối nội có thể ảnh hưởng đến khí huyết, làm mất đi sự hoạt động thông thường. Phàm là khi vui buồn, tức giận, hoài nghi, lo lắng, đều là loạn, là căn nguyên của bệnh tật và đoản thọ, không chỉ khi dưỡng bệnh mới không nên loạn, mà khi bình thường cũng rất kỵ tâm loạn.
24. Giận nhiều hại gan, dâm nhiều hại thận, ăn nhiều hại ruột, ưu tư hại lá lách, phẫn nộ hại gan, sầu muộn hại tinh thần.
25, Khi đổ bệnh, đều do tâm suy yếu, ngoại tà thừa cơ xâm nhập. Mà khi tâm yếu khí nhược, mỗi khi do tâm tình hỗn loạn, thân thể không sung mãn, xuất hiện đủ loại bất an, Tham ăn, tham thắng, tham đạt, tham vui an dật, đều đủ để dẫn đến bị bệnh. Khi tham mà không được, thì dễ dẫn đến giận dữ. Hay giận dữ khiến tâm khí hỗn loạn, gan mật rối loạn, sáu mạch chấn động, ngũ tạng sôi trào, ngoài tà cùng lúc đó mà thừa cơ xâm nhập, đó là nguyên nhân của bệnh tật.
26, Người thường mong cầu trường thọ, trước tiên phải trừ bệnh. Mong cầu trừ bệnh, phải biết dụng khí. Muốn biết dụng khí, trước hết phải dưỡng sinh. Phương pháp dưỡng sinh, trước hết phải điều tâm (điều hòa tâm thái).
27, Con người do khí trong ngũ hành mà sinh, nhục thân lấy khí làm chủ. Khí bị hao tổn ắt sinh bệnh, khí ứ động không thông cũng sinh bệnh. Muốn trị bệnh này, ắt phải trị khí trước tiên.
28. Khí để thông huyết, huyết để bổ khí, tuy hai mà như một vậy. Phàm là người nhìn nhiều (sử dụng mắt nhiều) ắt tổn thương huyết, nằm nhiều tổn thương khí, ngồi nhiều tổn thương thịt, đứng nhiều tổn thương xương, đi nhiều tổn thương gân, thất tình lục dục quá độ ắt tổn thương nguyên khí, hại tới tâm thận. Như ngọn lửa cháy mạnh mẽ, bị hao tổn dương khí.
29. Trị bệnh về ngũ tạng, đầu tiên cần bổ khí. Thận là cấp bách nhất. Bổ khí nghiêm cấm động tâm, động tâm ắt nóng gan, các mạch bị chấn động, chân thủy sẽ hao tổn. Tâm bị động, sẽ dẫn khởi phong. Phong động ắt hỏa vượng, hỏa vượng ắt thủy can, thủy can ắt địa tổn.
30. Tâm định thần nhất, người được chữa bệnh cần tín tâm kiên định chuyên nhất, lưỡng tâm tương hợp, có thể trị khỏi bách bệnh, không cần dùng thần dược.
31. Bệnh của con người có thể chia thành 2 loại: một là kinh lạc cơ bản thông suốt nhưng khí không đủ. Biểu hiện là thường xuyên đau chỗ này chỗ kia, đó là vì khí của anh ta không đủ để khí hóa thức ăn, từ đó sản sinh ra tương hỏa (cũng gọi là hư hỏa), thuận theo kinh lạc di chuyển hỗn loạn trong thân thể, chỗ nào thông thì chạy qua chỗ đó, gặp phải chỗ bị tắc nghẽn, chỗ đó ắt sẽ bị đau. Những người như vậy uống một chút thuốc liền lập tức thấy công hiệu. Hai là kinh lạc không thông, khí không có chỗ nào để lưu lại trong thân thể. Biểu hiện bề ngoài không có chút dấu hiệu nào của bệnh tật, nhưng một khi đã phát bệnh thì rất nặng, hơn nữa loại người này dù uống thuốc gì thì hiệu quả cũng rất chậm, hoặc căn bản không có tác dụng gì.
Chủ phát gọi là cơ. Mũi tên muốn bay ra từ cánh cung, bắt buộc phải có cái cơ này để phát động. Bất kỳ sự tình nào cũng đều như thế, đều có một cái cơ, chỉ khi nào kích động cái cơ này, thì sự tình mới phát sinh, nếu chẳng kích động được cái cơ này, các điều kiện khác dẫu có nhiều đến mấy, cũng không có cách nào dẫn khởi sự việc. Vậy rốt cuộc cơ nó là cái thứ gì, nó chính là nhân tố then chốt để phát sinh mọi sự việc. Nó là điểm, không phải là diện. Thế nhưng nếu kích động được điểm này, thì có thể kéo theo cả một diện. Cho nên bệnh cơ là nhân tố then chốt nhất trong sự phát sinh, phát triển và biến hóa của bệnh, (cũng có thể nói, bệnh cơ một khi khai mở, bệnh trạng của người đó sẽ hiển hiện ra, người đó sẽ tiến nhập vào trạng thái tuần hoàn ác tính của bệnh, đối lập với bệnh cơ là “sinh cơ”. Khi sinh cơ mở ra, người đó sẽ tiến nhập vào trạng thái thuần tốt đẹp của quá trình hồi phục. Thực tế bệnh cơ và sinh cơ là hai phương diện của cùng một thứ, là một cặp âm dương. Khi bệnh cơ mở ra, sinh cơ sẽ đóng lại; khi sinh cơ mở ra, bệnh cơ tự nhiên cũng sẽ đóng. Đây gọi là pháp biện chứng).
32. Cảnh giới cao nhất của Trung y là dưỡng sinh, cảnh giới cao nhất của dưỡng sinh là dưỡng tâm. Cho nên, đối với dưỡng sinh mà nói, hạ sỹ dưỡng thân, trung sỹ dưỡng khí, thượng sỹ dưỡng tâm. Nhìn một cá nhân cũng giống như thế, nhìn tướng không bằng nhìn khí, nhìn khí không bằng nhìn tâm.
33. Tâm thần bất an, tâm tình nóng vội, là căn nguyên dẫn đến bị bệnh và tử vong. Phương pháp giữ tâm bình an, là bí quyết số một trong việc bảo vệ sinh mệnh. Tâm có thể chủ động tất cả. Tâm định ắt khí hòa, khí hòa ắt huyết thuận, huyết thuận ắt tinh lực đủ mà thần vượng, người có tinh lực đủ thần vượng, lực đề kháng nội bộ sẽ khỏe, bệnh tật sẽ tự tiêu tan. Cho nên để trị bệnh đương nhiên cần lấy dưỡng tâm làm chủ [yếu].
34. Phong hàn âm dương mùa hạ nóng ẩm, đều có thể khiến cho con người mắc bệnh. Ngộ nhỡ lực đề kháng yếu, [bệnh tật] sẽ thừa cơ xâm nhập. Người có thân thể yếu nhược thường nhiều bệnh, chính là cái lý này. Người giàu có điều kiện bảo hộ tốt, như ăn-mặc-ở v.v… Người nghèo có lực đề kháng, nếu như khí đủ thần vượng, lỗ chân lông dày khít, không dễ bị [bệnh tật] xâm nhập v.v… Người giàu ăn nhiều đồ béo ngọt, hại dạ dày hại răng. Người nghèo hay phải chịu đói, thức ăn không phức tạp, nhờ đó mà không bị bệnh ở ruột. Người giàu thường nhàn hạ, vì thế mà nhiều phiền muộn. Người nghèo lao động nhiều, nhờ đó mà bệnh tật ít. Người giàu không tạo phúc mà chỉ hưởng phúc, chỉ toàn tiêu phúc, tiêu cạn ắt nghèo. Người nghèo có thể cần kiệm, đó chính là tạo phúc, khi quả chín sẽ giàu có. Phàm là điều kiện bảo hộ ăn-mặc-ở đầy đủ thì lực đề kháng về tinh khí thần sẽ yếu. Điều kiện bảo hộ kém, lực đề kháng ắt sẽ mạnh.
35. Mới khỏi bệnh nặng, cần tránh cắt tóc, rửa chân, tắm gội
36. Con người đều muốn cầu trường thọ vô bệnh, thân thể luôn khỏe mạnh. Muốn thân thể khỏe mạnh, đương nhiên cần điều tiết tinh khí thần. Muốn điều tiết tinh khí thần, đương nhiên cần cự tuyệt sự can nhiễu của những thứ tà. Muốn chặn đứng tà, đầu tiên cần phải dưỡng tâm. Muốn dưỡng tâm, cần phải hóa giải tam độc tham-sân-si. Muốn hóa giải tam độc này, bắt buộc phải học tâm giới. Nhưng muốn giữ được giới về ngôn từ lời nói, không nói không làm những việc vô ích, cần phải khai [trí] huệ, vứt bỏ đi những điều ngu muội, và bắt buộc phải đạt được định trước tiên. Muốn đạt được định, tất phải học tản bộ.
37. Có thể tĩnh ắt phải là người nhân [nghĩa], có nhân [nghĩa] ắt sẽ thọ, có thọ chính là hạnh phúc thực sự.
38. Tất cả những pháp môn tu thân tu tâm, chỉ có bí quyết gồm 2 từ: một là phóng hạ, hai là quay đầu. Phóng hạ đồ đao, lập địa thành Phật; Biển khổ vô biên, quay đầu là bờ. Chỉ cần phóng hạ, quay đầu, người bệnh lập tức khỏi, người mê lập tức giác ngộ. Đây mới thực sự là người có vô lượng thọ.
39. Người mà tâm quá lao lực, tâm trí mệt mỏi thì gan sẽ vượng, tâm quá lao lực chính là tâm quá đầy, không rỗng. Tâm đầy, ắt không thể dung nạp can (mộc) sinh chi hỏa, tâm không dung nạp can sinh chi hỏa, khí trong gan ắt sẽ tích tụ lại nhiều. Gan là mộc khắc thổ, nên tì vị sẽ mắc bệnh, tiêu hóa sẽ không tốt, dinh dưỡng không đủ, tối ngủ sẽ không yên. Mộc lại khắc thủy, từ đó mà thận thủy bị thiếu, thủy không đủ ắt hỏa càng vượng, tâm thận có liên hệ tương hỗ, nên tâm khí càng yếu, bệnh phổi sẽ hình thành. Nội bộ có mối liên quan tương hỗ, một thứ động sẽ kéo theo toàn bộ đều động, một chỗ bị bệnh sẽ khiến toàn cơ thể bị bệnh. Người có cái tâm nhiễu loạn, chính là do cái tâm ngông cuồng đầy tham vọng, cho nên muốn trị bệnh cần làm an cái tâm này lại, an cái tâm này lại chính là chấm dứt vọng tưởng, để chấm dứt vọng tưởng cần có tâm sáng, tâm sáng chính là tự giác ngộ, mà để đạt được khỏe mạnh thì công hiệu nhất lại là ở tản bộ.
40. Tản bộ là phương pháp điều hòa tâm, tâm điều hòa ắt thần an (tinh thần an lạc), thần an ắt khí đủ, khí đủ ắt huyết vượng, khí huyết lưu thông, nếu có bệnh có thể trừ bệnh, nếu không đủ có thể bồi bổ, đã đủ rồi có thể gia tăng. Bệnh hiện tại có thể trừ, bệnh tương lai có thể phòng tránh. Điều tâm còn khiến cho thần minh (tinh thần minh mẫn sáng suốt), thần minh ắt cơ linh, người có tâm thanh tĩnh thật tuyệt diệu biết bao, họ có cái nhìn biện chứng, tác phong bề ngoài linh hoạt, thấu hiểu các nguyên lý một cách chính xác, liệu sự nhìn xa trông rộng, gặp loạn bất kinh, thấy cảnh đẹp không bị mê hoặc, có thể thông đạt mọi thứ, bản thân không có những ý kiến chủ quan sai lệch, đại cơ đại dụng, chính là từ đó mà ra.
41. Con người khi bị bệnh kỵ nhất là khởi tâm oán giận. Lúc này nhất định phải giữ sự bình an hòa ái, khiến cho tâm an định. Sau đó dần dần điều chỉnh, sức khỏe sẽ rất nhanh hồi phục. Tâm an thì khí mới thuận, khí thuận mới có thể trừ bệnh. Nếu không ắt tâm sẽ gấp hỏa sẽ thăng, can khí sẽ phải chịu hao tổn, làm bệnh tình càng thêm nặng. Tâm thân yên nhất, khí huyết toàn thân ấy, sẽ tự phát huy tác dụng khôi phục sức khỏe.
42. Giờ Tý (từ 11 giờ đêm đến 1 giờ sáng) mất ngủ, thủy thận tất thiếu, tâm thận có liên hệ tương hỗ, thủy thiếu ắt hỏa vượng, rất dễ tổn hại tới [tinh] thần.
43. Trong khi ngủ nếu có tư tưởng, tâm không thể an, không được vừa nằm vừa suy nghĩ trăn trở, rất dễ hao tổn [tinh] thần.
44. Giờ Ngọ (từ 11 giờ đến 13 giờ) thuộc về tâm, giờ này có thể tản bộ 15 phút, nhắm mắt dưỡng thần, tâm khí ắt khỏe mạnh.
45. Dậy sớm trong khoảng giờ Dần từ 3 giờ đến 5 giờ, giờ này kỵ nhất buồn giận, nếu không ắt hại phổi tổn thương gan, hy vọng mọi người hết sức chú ý.
46. Tất cả sự nghiệp trong cuộc đời, đều lấy tinh thần làm căn bản, sự suy vượng cường thịnh của tinh thần, đều dựa vào sự tĩnh định bất loạn của tâm và thần, một chữ loạn, cũng đủ để làm trở ngại tới công việc.
47. Nhân sinh lấy khí huyết lưu thông làm chủ, khí ứ đọng có thể ngăn trở huyết, máu huyết bị ngăn trở có thể tích độc thành nhọt thành bệnh, thành u thành ung thư, tất cả đều là do huyết khí không thông tạo thành. Khí lấy thuận làm chủ, huyết lấy thông làm suôn sẻ. Căn nguyên bách bệnh đầu tiên đều do khí tắc, khí bị tắc bên trong, gan sẽ bị thương tổn trước tiên. Cách cứu chữa, chính là ở bí quyết hóa giải. Mà bí quyết hóa giải lại gồm có 2 loại: Một là tìm căn nguyên của nó, căn nguyên này chính là ở tâm, tâm không ắt tất cả tự động được hóa giải. Hai là dùng thuốc và châm cứu, trợ giúp hóa giải thêm bằng mát xa, sẽ giúp cho khí huyết lưu thông.
48. Dưỡng bệnh trị bệnh không thể đòi hỏi nhanh. Bởi vì nóng vội sẽ trợ giúp hỏa, hỏa vượng sẽ tổn khí, gây tác dụng ngược lại. Ngoài ra không thể tham nhiều, tham lam ắt tâm không kiên định mà nóng vội, huống hồ bách bệnh đều do tham mà ra, nên không thể lại tham mà làm cho bệnh tình càng thêm nặng là vậy.
49. Tâm thuộc tính Hỏa, Thận thuộc tính Thủy, Tâm Thận liên hệ tương hỗ. Hỏa cần giáng hạ, Thủy cần thăng lên, Thủy Hỏa tương tề, ắt khí trong thân thể sẽ bộc phát. Các bộ phận cơ thể vận động, có thể được mạnh khỏe. Điều này qua việc quan sát lưỡi có thể biết được. Lưỡi không có nước ắt không linh hoạt, vì chữ hoạt (活) là do bộ Thủy và chữ lưỡi (舌) ghép thành. Lưỡi có thể báo cáo tình trạng nặng nhẹ của các loại bệnh bên trong thân thể, từ đó mà phán đoán việc sinh tử.
50. Phương pháp tự cứu khi lâm đại bệnh: Một là không được sợ chết, tin tưởng rằng bệnh của mình, không những có thể khỏi, mà thân thể có thể trở nên đặc biệt khỏe mạnh, sống lâu trường thọ. Bởi vì bản thân cơ thể bản chất đã có năng lực này, không phải chỉ là suy nghĩ để tự an ủi. Hai là tin tưởng không cần dùng thuốc hoặc dựa vào bất kỳ thực phẩm dưỡng sinh nào, nhất định bản thân tự có khả năng trừ bệnh kéo dài tuổi thọ. Ba là bắt đầu từ hôm nay, phải quyết định không được lại động tới thân bệnh của bản thân, không được nghĩ tới bệnh của bản thân là bệnh gì, tốt hay xấu đều không được suy tính về nó, chỉ làm một người vô tư. Bốn là trong khoảng thời gian chữa trị, không được nghĩ tới công việc, cũng không được hối hận về công việc và thời gian đã mất, chuyên tâm nhất trí, nếu không sẽ lại chậm trễ có khi hỏng việc.
51. Phương pháp dưỡng tĩnh: an tọa (nằm) trên giường, đặt thân tâm nhất tề hạ xuống, toàn thân như hòa tan, không được phép dùng một chút khí lực nào, như thể không có cái thân thể này vậy, hô hấp tùy theo tự nhiên, tâm cũng không được phép dùng lực, một niệm khởi lên cũng là đang dùng lực. Để tâm đặt xuống tận dưới bàn chân, như thế có thể dẫn hỏa đi xuống, dẫn thủy đi lên, tự nhiên toàn thân khí huyết sẽ thông thuận.
52. Yếu quyết tu luyện: tĩnh lặng theo dõi, tránh dùng lực
Yêu cầu cụ thể: Không cho phép bất cứ bộ phận nào dùng khí lực dù chỉ một chút, bao gồm ý niệm, hô hấp, tứ chi, cần làm được: mắt không nhìn, tai không nghe, mũi không ngửi, lưỡi không nếm, miệng không nạp (ăn), tâm không nghĩ. Đó là điều kiện duy nhất. Nếu có bất cứ hành vi tư tưởng, nghe, cảm giác nào đều là đang dùng khí lực, thậm chí cử động ngón tay cũng là dùng khí lực. Thở mạnh cũng lại là dùng khí lực. Không bao lâu hơi thở sẽ tự nhiên trở nên an hòa, như thể không phải ra vào từ lỗ mũi, mà như thể 8 vạn 4 ngàn lỗ chân lông trên toàn cơ thể đều có động tác, hoặc nở ra hoặc khép lại, lúc này sẽ là trạng thái vô ngã vô thân vô khí vô tâm, tự nhiên tâm sẽ quy hồi vị trí bản nguyên. Cái gọi là dẫn hỏa quy nguyên, hay còn gọi là thủy hỏa ký tế, chính là bí quyết chung để điều trị bách bệnh.
53. Trường hợp chăm chút dưỡng sinh nhưng lại chết sớm, chiếm đến ba phần mười, vậy rốt cuộc là thế nào? Đó là vì quá yêu quý thân thể của mình. Vì cái thân xác này, sợ phải chịu xấu hổ, sợ bị nuông chiều, sợ chịu thiệt, sợ bị mắc lừa, lo trước lo sau, nhìn ngang nhìn dọc, lo lắng hốt hoảng, tính toán thiệt hơn … như thế, trái tim đó của anh ta cả ngày giống như quả hạch đào bị chó gặm đi gặm lại, làm sao mà có thể không chết chứ. Càng sợ chết, càng chết nhanh. Nếu bạn muốn dưỡng sinh, thì phải không sợ chết. Chỉ có không sợ chết, mới có thể cách xa cái chết.
Người thực sự không sợ chết, đi đường sẽ không gặp phải hổ, nếu có gặp phải, hổ cũng không ăn thịt anh ta. Đánh nhau không gặp phải đao súng, nếu có gặp, đao súng cũng sẽ không làm anh ta bị thương. Tại sao? Bởi vì anh ta không coi cái chết là gì, không sợ chết, cái chết cũng không có cách nào. Dưỡng sinh, mặc dù không phải là mục đích của việc tu đạo, nhưng người tu đạo đã nhìn thấu được sinh tử, cho nên sẽ không sợ chết nữa, vì đã không sợ chết nữa, nên cái chết cũng không còn là vấn đề. Quan sinh tử đã qua rồi, còn gì mà không thể vượt qua nữa? Vì thế, người tu đạo có thể trường sinh. Không nghĩ đến trường sinh, trái lại lại có thể trường sinh. Tâm luôn nghĩ muốn trường sinh, trái lại càng nhanh chết. Trường sinh không phải là mục đích của tu đạo, nó chỉ là hiện tượng đi kèm của tu đạo.
54. Người có bệnh, lại không cho rằng mình có bệnh, đây chính là bệnh lớn nhất của con người. Người mà biết bản thân mình có bệnh liệu có được bao nhiêu?
55. Người mà ngày nào nửa đêm canh ba cũng vẫn còn ở trên mạng, bản thân đó chính là điều đại kỵ của dưỡng sinh. Bao gồm cả một số người gọi là danh y cũng thế. Ngoài ra, tâm của họ còn luôn tính toán so đo, thử hỏi người như vậy thì đến bản thân còn không giữ nổi, thì làm sao chữa bệnh cho người khác đây?
56. Đừng tham những cái lợi nhỏ nhặt, cái lợi lớn cũng đừng tham. Một từ tham nhưng bao hàm cả họa. Tham lam, suy tính thiệt hơn sẽ khiến cho người ta mắc các bệnh về tim. Tham lam, suy hơn tính thiệt là biểu hiện của việc không hiểu Đạo Pháp về cái lý tự nhiên.
57. Đừng có ngày nào cũng nghĩ xem ăn cái gì để bổ âm, ăn cái gì để tráng dương. Hãy nhớ kỹ, vận động là có thể sinh dương; tản bộ thì có thể sinh âm. Âm là mẹ của dương, dương là được vận dụng bởi âm.
58. Người ta khi khí không đầy đủ, không được mù quáng mà bổ khí, nếu không ắt sẽ ảnh hưởng đến sức khỏe. Nếu như vì huyết không đủ, thì cần phải bổ huyết trước, bởi vì huyết là mẹ của khí, nếu không ắt sẽ thành dụng cụ thiêu đốt, làm cho nội tạng bị đốt cháy; nếu là vì kinh lạc không thông, thì có thể gia tăng khí huyết, đồng thời bồi bổ khí huyết. Như vậy mới có thể đạt được tác dụng của bổ khí.
59. Hoàn cảnh đối với người dưỡng sinh có tính trọng yếu là điều vô cùng rõ ràng. Đây chính là đạo lý mà vì sao người ở những vùng không khí trong lành nơi rừng sâu núi thẳm, có thể dưỡng khỏi những bệnh tật khó chữa. Bởi vì những vật chất tinh vi nơi rừng sâu núi thẳm (ion điện âm) sẽ thông qua trạng thái thả lỏng của con người trong khi hít thở sâu mà hấp thụ vào trong nội bộ nhân thể, từ đó mà tưới đều lục phủ ngũ tạng, khiến cho người ta có được sức sống mới. Ngoài ra còn có một điểm mà người thường không hề biết, đó chính là con người không chỉ hô hấp thông qua lỗ mũi, mà mỗi một lỗ chân lông trên thân thể con người đều có thể hô hấp, hơn nữa những gì chúng hấp thụ chính là tinh hoa của trời đất.
60. Con người trong trạng thái thả lỏng và tĩnh, hít thở sâu và chậm có thể cảm nhận được sự giao hoán những tinh khí của con người với trời đất: Trong khi hấp thụ khí, thực tế ngoại trừ lúc phổi đang hít khí vào, toàn bộ thân thể đều đang bài trừ khí bên trong thân thể ra ngoài, và đem khí của người phóng thích ra ngoài trời đất; còn khi phổi đang thải khí ra, thực tế con người đang hấp thụ tinh khí của đất trời thông qua các lỗ chân lông. Điều này đại khái chính là điều mà Lão Tử đã nói “Thiên địa chi gian, kỳ do thác dược hồ”.
61. Khi vận động có hai điểm cấm kỵ: một là không được vận động khi khí huyết không đủ; hai là không được vận động trong môi trường bị ô nhiễm.
62. Vận động có hai tác dụng: một là gia tăng tốc độ vận hành của khí huyết, thúc tiến quá trình bài xuất chất cặn bã trong thân thể ra ngoài; hai là khai mở lỗ chân lông trên da, để hấp thụ tinh khí của trời đất.
63. Ngộ tính là gì? Trí huệ là gì? Ngộ tính và trí huệ chính là sử dụng những phương pháp đơn giản nhất để xử lý, xem xét tất cả các sự vật. Nhưng có một số người thường hay gây nhiễu loạn luôn nhìn những sự việc đơn gian thành phức tạp, làm thành phức tạp. Phức tạp và đơn giản kỳ thực là một thứ, là hai mặt của một thứ. Điều người thông minh nhìn thấy là mặt đơn giản, điều người ngu xuẩn nhìn thấy là mặt phức tạp.
64. Con người không trị được bệnh, thì cần phải nhờ Thần trị; Thần trị không khỏi bệnh thì phải nhờ Phật trị. Phật giảng điều gì? Điều Phật giảng là tâm.
65. Bệnh viện và tòa án ngày nay đều như nhau, có động tới hay không cũng đều đưa cho bệnh nhân giấy thông báo phán quyết tử hình. Mà trong nhiều tình huống, phán tử hình cho nhiều người đáng lẽ không bị tử hình. Tại sao lại nói như thế? Lấy “ung thư” làm ví dụ, trong tâm con người ngày nay ung thư đồng nghĩa với tử hình. Kỳ thực nếu như chúng ta không gọi nó là ung thư, thế thì đối với bệnh nhân mà nói, chính là mang cho bệnh nhân một tia hi vọng, bằng như lưu lại cho họ một cơ hội sống. Cho nên tôi mới nói, bệnh nhân ung thư ngày nay có đến hơn một nửa là bị dọa chết, là bị áp lực tinh thần dày vò đến chết. Đồng thời cũng chính là bị bệnh viện hành hạ đến chết.
Bởi vì một khi bạn bị chẩn đoán thành bệnh ung thư, họ sẽ có thể không kiêng nể gì cả mà tùy ý xử lý bạn, điều trị mà không chết coi như mệnh của bạn lớn, điều trị mà chết, thì là do bệnh của bạn là ung thư. Sự thực mà nói, không có bệnh gì là trị không khỏi, chỉ là xem cái tâm của bạn có thể buông xuống được không, tất cả bệnh tật đều từ tâm sinh, tất cả bệnh tật cũng đều từ tâm mà trị. Chỉ cần bạn vẫn còn sống, bạn vẫn còn cơ hội. Tìm thấy được cơ hội này, áp dụng nó đối với việc trị bệnh ung thư, bạn sẽ khỏe mạnh trở lại.
66. Hiện nay ngoài xã hội đều nói về cạnh tranh, việc này đã khiến cho mọi trật tự bị đảo loạn, khiến cho con người bị dẫn dụ vào ma đạo. Cạnh tranh là gì? Cạnh tranh chính là khiến người ta bị cuốn vào cảnh giới tham dục vô hạn. Một mặt bạn đề xướng cạnh tranh, một mặt bạn nói về những gì là xây dựng và ổn định xã hội, đây chẳng phải là điển hình của việc tự lừa mình dối người sao.
67. Căn cứ vào nguyên lý âm dương tương hỗ mà xét, thanh khiết và vẩn đục là hấp dẫn lẫn nhau. Cho nên con người ăn vào những thứ tươi mới tất sẽ có tác dụng tương hợp với những vật chất bẩn trong cơ thể, từ đó mà bài trừ những thứ ấy ra ngoài.
68. Những vật chất vẩn đục sinh ra là do ăn vào những thực phẩm không sạch, nhưng chủ yếu là do ăn quá nhiều, cơ thể không thể tiêu hóa được khiến đống thức ăn thừa đó biến thành cặn bã.
69. Tùy kỳ tự nhiên là cảnh giới cao nhất của dưỡng sinh. Một người khi sinh ra, vận mệnh của anh ta căn bản là đã có định số rồi. Anh ta nên làm gì, không nên làm gì, nên ăn gì, không nên ăn gì, nếu như có thể thuận theo vận số của bản thân mà làm, thì sẽ có thể được bình an vô sự. Người có ngộ tính sẽ phát hiện ra được, sẽ biết được vận mệnh của bản thân, biết được họ nên làm cái gì, không nên làm cái gì. Cho nên dưỡng sinh tuyệt đối không đơn giản là bắt trước, bảo sao làm vậy.
Không cần hâm mộ người khác, cần tìm ra ngộ tính của bản thân từ trong tâm của chính mình. Vậy con người làm thế nào mới có thể phát hiện bản thân đã đạt được tùy kỳ tự nhiên hay chưa? Kỳ thực điều này quá dễ, khi bạn có bệnh, bạn cảm thấy không thoải mái, bạn thấy không được tự tại, chứng tỏ bạn đã đi ngược lại tự nhiên rồi. Cần làm được thuận theo tự nhiên của đại tự nhiên bên ngoài, ngoài ra còn phải thuận theo lẽ tự nhiên của vận mệnh bên trong bản thân, hai điều này đều không thể thiếu được.
70. Rất nhiều người khi nghe thấy bác sỹ tuyên bố bản thân bị mắc trọng bệnh, thường đều sẽ biểu hiện ra dáng vẻ không vui, hi vọng có thể dùng phương pháp cắt, gọt, độc, giết v.v… để loại bỏ căn bệnh đó, tuy nhiên, bệnh tật thực sự không phải sản sinh từ đó? Trên thế gian tuyệt đối không có hiện tượng “đang khỏe mạnh đột nhiên sinh bệnh”. Lấy cảm mạo làm ví dụ, nếu thực sự yêu cầu bệnh nhân tự làm kiểm điểm, thông thường bệnh nhân sẽ cho biết, bản thân trước khi cảm mạo, đã trải qua vài lần thức thâu đêm; có người sẽ nói rằng bản thân bị trúng gió lạnh, bị dính mưa ướt; có một số người lại nói do áp lực công việc quá lớn, thường xuyên đau đầu, mất ngủ. Kỳ thực, những hiện tượng như thế, đều có thể là nhân tố dẫn tới cảm mạo, nói thêm nữa, nếu như độ mẫn cảm và tính cảnh giác của con người đầy đủ, tự nhiên sẽ có thể đạt được mục đích “đề phòng tai họa”.
71. Khoa học chân chính là gì? Chính là nhân duyên quả báo. Không tin nhân quả, thì không phải là khoa học chân chính.
72. Cái tâm không sợ chịu thiệt, không sợ bị người khác chiếm lấy lợi ích. Hay nói một cách khác là bạn có thể chịu thiệt, người khác muốn lấy mạng của bạn mà bạn vẫn có thể buông xả, bạn đều có thể cho họ hết, hơn nữa tự bản thân trong bất kỳ hoàn cảnh nào đều không ham lợi ích, khi đó cái tâm của bạn có thể sẽ không định (tĩnh lặng) sao? Con người trên thế gian có ai làm được? Nhưng Phật là có thể làm được.
73. Sau khi con người nắm vững được phương pháp về sức khỏe, họ sẽ thực sự hưởng thụ được một trạng thái tự tin khi không còn lo sợ mắc bệnh. Cái loại cảm giác này thật tuyệt, hy vọng rằng bạn và chúng tôi đều có thể có được trạng thái tự tin đó.
74. Khi học vấn thâm sâu ý chí sẽ bình lặng, tâm định ắt khí sẽ yên. Cho nên đối với một người đắc Đạo mà nói, quan sát một người, không phải là một việc quá khó khăn, đây cũng là kết quả của tướng tùy tâm chuyển.
75. Danh là điều khó phá vỡ nhất trong ngũ dục, sắc đứng thứ hai, tiếp theo là tài, sau đó là ăn và ngủ. Tâm về danh không bỏ, thì không có cách nào nhập Đạo.
76. Khởi nguồn của bách bệnh, đều bắt nguồn từ việc bị gió độc thừa cơ xâm nhập. Nếu như thân thể khí suy nhược, khả năng phòng vệ kém, hoặc ưu tư sợ hãi, đắm chìm trong tửu sắc, làm việc quá lao lực, chân khí sẽ bị hao tổn từ đó tà ngoại thừa cơ tấn công.
77. Trị bệnh về ngũ tạng, đầu tiên cần phải bổ khí. Khi bổ khí cấm động tâm, tâm động ắt gan vượng, gây chấn động mạch, chân thủy sẽ hao tổn. Tâm là quạt, sẽ dẫn khởi gió. gió động ắt hỏa vượng, hoặc vượng ắt thủy can, thủy can ắt địa tổn.
78. Đối với bác sỹ mà nói, tâm định thần nhất, người được chữa bệnh có tín tâm kiên định, lưỡng tâm tương hợp, có thể trị được bách bệnh.
79. Qua trường hợp Hitler đi vòng qua phòng tuyến kiên cố Maginot của quân đội liên minh, tôi ngộ ra rằng: để đối phó với một số bệnh cứng đầu, không thể tấn công cứng nhắc từ chính diện, cần đột phá từ những phương diện khác có liên quan. Chẳng hạn như việc điều trị các bệnh cứng đầu như bệnh thận, bệnh gan, có thể đạt được hiệu quả thông qua việc điều chỉnh phổi và lá lách v.v…
80. Trung Dung, là nguyên tắc căn bản của dưỡng sinh. Khí huyết trong cơ thể người cũng là một cặp âm dương, huyết là âm là thể, khí là dương là dụng. huyết là mẹ của khí, khí là chủ tướng của huyết. Khí không đủ, dễ mắc các bệnh do ứ trệ tạo nên như mọc u, tắc động mạch; khí quá độ; dễ mắc các bệnh về xuất huyết não. Cho nên, chỉ khi khí huyết cân bằng, con người mới có thể khỏe mạnh.
81. Con người chỉ khi ngộ ra được cái gì là “tự nhiên”, mới được coi là đắc đạo. Biết được tự nhiên, sau đó mới có thể tùy kỳ tự nhiên. người này chính là Thần nhân. Hiểu được âm dương, hiểu được tùy kỳ tự nhiên, bạn nhất định sẽ trở thành lương y đại đức.
82. Cái gì là tự nhiên, tự nhiên chính là bất kỳ sự vật gì đều có hai mặt âm dương, bất kỳ sự vật nào đều cần trải qua quá trình Sinh (sinh sản), Trưởng (tăng trưởng), Thu (thu hoạch), Tàng (tàng trữ). Bạn thuận theo quá trình này, sử dụng nguyên lý tương sinh tương khắc của ngũ hành để điều tiết sự cân bằng của bệnh nhân, làm sao mà không trị được khỏi bệnh chứ.
83. Đơn giản và phức tạp là một cặp âm dương, sự tình càng phức tạp, thường thường sử dụng biện pháp đơn giản nhất lại có thể giải quyết. Cũng đồng dạng như thế, một vấn đề nhìn tưởng chừng đơn giản, để giải quyết nó bạn sẽ thấy thật không dễ dàng, bạn phải phó xuất nỗ lực rất lớn cũng không nhất định giải quyết được. Điều này giống cương nhu vậy, cực nhu có thể khắc chế cương, cực cương thì nhu cũng không thể chống. Cho nên, chúng ta khi giải quyết vấn đề cần có lối suy nghĩ rằng, gặp phải vấn đề phức tạp nên tìm biện pháp đơn giản để giải quyết, gặp phải vấn đề đơn giản đừng vội coi thường nó, cần phải chú trọng đủ mức tới nó.
84. Chúng ta hãy thử xem trong thế giới này có phải là có tồn tại đạo lý đó hay không. Liệu có được mấy người có thể tùy kỳ tự nhiên trong việc ăn ngủ, có được mấy người có thể tuân thủ tự nhiên. Bạn tuân thủ không được, vì sao? Bởi vì nó quá đơn giản, chính vì quá đơn giản, cho nên bạn không dễ mà có thể tuân thủ. Đây gọi là phép biện chứng.
85. Cái gì là cân bằng? Cân bằng chính là sự tồn tại dựa vào nhau và khắc chế nhau của âm dương, phương diện nào quá độ hoặc quá kém cũng sẽ khiến mất đi sự cân bằng. Tổn thương nguyên khí là gì, mất đi sự cân bằng chính là tổn thương nguyên khí. Thường xuyên ở trong trạng thái cân bằng, nguyên khí ắt sẽ được bảo trì tốt, con người sẽ lão hóa chậm.
86. Đạo về âm dương chính là sự tương hỗ dựa vào nhau và chuyển hóa lẫn nhau của hai phương diện mâu thuẫn đối lập. Bất kỳ một cặp mâu thuẫn nào, nếu một bên thoát ly khỏi bên kia, không còn chịu sự ức chế của đối phương nữa, thì thời điểm mà nó bị diệt vong cũng không còn xa. Bạn thử nhìn xem, xã hội ngày nay, các lãnh đạo đều không thích bị khống chế, thích được độc lập tự do, thích làm theo ý mình, tham ô hối lộ, thế thì kết quả là gì đều có thể tưởng tượng ra được. Âm và dương chính là như thế. Trong đại tự nhiên, khi một sự vật xuất hiện, đều có mang theo nhân tố do nó sinh ra, nhưng đồng thời cũng sẽ xuất hiện một nhân tố để khắc chế nó. Đó chính là đạo lý ngũ hành tương sinh tương khắc, cũng là đạo lý dựa vào nhau, ức chế lẫn nhau của âm dương. Cho nên đạo lý dưỡng sinh cũng vậy, khi bạn bị bệnh, luôn tồn tại một nhân tố khiến bạn sinh bệnh, đồng thời cũng sẽ có một nhân tố ức chế nó, có thể giúp bạn tiêu trừ nhân tố gây bệnh. Tương tự như thế trong thế giới tự nhiên, tại chỗ có tồn tại rắn độc, chắc chắn khu vực xung quanh sẽ có tồn tại loại thảo dược có thể giải độc.
87. Cái gì gọi là đắc ý vong hình (vì đắc ý mà quên đi dáng vẻ vốn có của mình) ? Anh ta đã mất đi sự khống chế, mất đi sự ức chế của mặt âm, cho nên kết quả nhất định là …. cũng như thế con người không nên để tinh thần sa sút, vì như thế sẽ mất đi sự ức chế của mặt dương đối với họ.
88. Làm thế nào để có đại trí huệ? Nếu không có tấm lòng quảng đại, ở đâu mà có đại trí huệ chứ.
89. Tục ngữ có nói, sống đến già, học đến già. Học tập cũng cần phải hợp thời, đến tuổi nào thì học những điều mà ta nên học vào giai đoạn ấy, nếu không ắt sẽ không hợp thời, không tùy kỳ tự nhiên. Nhưng hãy xem sự giáo dục của chúng ta ngày nay, từ nhà trẻ đến đại học, có bao nhiêu điều là đáng để học. Lúc còn nhỏ nên học cái gì. nên học đạo đức, học hiếu đạo, tiếp theo là học nhận biết chữ, dấu chấm câu, tiếp theo là học cách làm việc. Đến tuổi thanh niên thì học cách làm sao để sống tốt giáo dục con cái tốt, làm cho gia đình hạnh phúc. Đến tuổi trung niên, học tập đạo dưỡng sinh. Đến những năm tuổi già, học cách buông bỏ tâm thái, an hưởng tuổi già. Ngành giáo dục cần học gì, chính là học những thứ này.
90. Tình chí (7 loại tình cảm của con người) đối với bệnh tật có mối tương quan mật thiết với nhau, có một số bệnh tật là do tình chí gây ra, bạn dùng thuốc trị liệu, trị mãi mà vẫn không khỏi, đối với loại bệnh tật này, muốn cởi chuông thì phải tìm người buộc chuông. Ngũ chí có thể gây bệnh, ngũ chí cũng có thể giải trừ bệnh.
91. Dưỡng sinh có một điều rất trọng yếu, đó là không được sợ chết. Người sợ chết dương khí không đủ, dương khí không đủ, tử thần sẽ tìm ra được bạn. Đây chính là điều mà đạo gia giảng, người tu luyện cần có một khí chất anh hùng. Nhân, trí, dũng không thể thiếu một trong ba.
92. Khi nào bạn lấy học vấn lý giải được nó là vô cùng đơn giản và bình dị, lúc này bạn mới là chân chính đạt được một trong tam muội. Nếu như bạn vẫn còn cảm thấy nó là bác đại tinh thâm, thâm sâu không thể đo lường, chứng tỏ bạn vẫn chưa nắm được tinh túy của nó, mới chỉ nhìn thấy phần tươi tốt của lá cây, mà vẫn chưa nhìn thấy được căn bản của nó, lúc này bạn mới chỉ ở giai đoạn “có”, vẫn chưa đặt được cảnh giới của “vô”. Tất cả đều không thoát được âm dương, vạn sự vạn vật đều không thoát khỏi được âm dương. Căn bản của điều này chính là âm dương. Biết được một điều này, mọi sự đều có thể hoàn thành.
93. Tập trung tinh thần định khí, quên đi cả bản thân và mọi sự vật. Đó là cốt lõi của dưỡng sinh
94. Chủ minh ắt hạ an, theo đó để dưỡng sinh ắt sẽ thọ, tình thế sống chết cũng không nguy hiểm, thiên hạ ắt sẽ hưng thịnh. Chủ bất minh ắt thập nhị quan gặp nguy, khiến cho đạo tắc nghẽn không thông, thực thể liền bị thương tổn, theo đó để dưỡng sinh ắt sẽ mang họa, người trong thiên hạ, và gia tộc này sẽ gặp đại nguy, nghiêm cấm nghiêm cấm !
95. Ứng dụng của ngũ hành tương sinh tương khắc: Phàm là do ngũ tạng hoạt động thái quá sẽ gây ra bệnh tật, đều có thể dùng phương pháp ngũ hành tương sinh tương khắc để trị. Giống như thế, phàm là vì ngũ hành không đủ dẫn khởi bệnh tật thì đều có thể dùng phương pháp ngũ hành tương sinh tương khắc để giải quyết. Đây là nguyên tắc căn bản của phép vận dụng ngũ hành.
96. Người hiện đại thường chú trọng vào phương diện truy cầu đề cao chất lượng cuộc sống, hậu quả của loại truy cầu này rất đáng sợ. Cần biết, dục vọng của con người đối với vật chất là không có giới hạn. Khi mà loại dục vọng này không được khống chế, cũng tương đương sự thống khổ không có giới hạn của chúng ta. Kỳ thực, vật chất có thể đem lại sự hưởng thụ, thì tinh thần cũng có thể; thuốc có thể trị bệnh, thì phương pháp trị liệu tâm lý cũng có thể làm được. Cho nên, chúng ta dùng cả cuộc đời để truy cầu tài phú, thì chi bằng hãy dùng quãng thời gian ấy để bồi dưỡng một loại tâm thái tốt, khiến cho tinh thần của chúng ta đạt tới một loại cảnh giới siêu phàm.
97. Sau khi con người nắm vững được phương pháp về sức khỏe, họ sẽ thực sự hưởng thụ được một trạng thái tự tin khi không còn lo sợ mắc bệnh. Cái loại cảm giác này thật tuyệt, hy vọng rằng bạn và chúng tôi đều có thể có được trạng thái tự tin đó.
98. Thân thể của chúng ta là một cơ thể có đầy đủ trí tuệ và chức năng, thân thể của chúng ta có rất nhiều “lính gác” như: răng, ruột thừa, a-mi-đan v.v… Khi thân thể chúng ta có hiện tượng dị thường (thông thường là “thăng hỏa”), những lính canh này sẽ lập tức phản ứng thông báo tới đại não. Người thông minh lúc này nên điều tiết lại tâm thái, kiểm điểm bản thân, để thân thể cân bằng hài hòa trở lại. Vậy mà hiện nay Tây y đều làm những việc gì? Bạn bị đau đúng không, tôi sẽ cắt bỏ bộ phận bị đau của bạn. Hiện nay thậm chí còn có người, phát minh ra một loại máy, bạn bị viêm mũi dị ứng sẽ phải hắt xì hơi đúng không? Vậy tôi sẽ đốt cháy khu vực thần kinh mẫn cảm trong mũi của bạn, như thế sau này mũi bạn có bị kích thích gì đi nữa cũng sẽ không bị hắt hơi. Hậu quả của những việc làm như thế của Tây y chính là sau này nếu chúng ta lại tiếp tục bị bệnh, thì bộ phận bị cắt bỏ chính là lục phủ ngũ tạng của chúng ta.
99. Hãy nhớ kỹ, khi chúng ta ngẫu nhiên bị đau bụng, hắt hơi, ho, phát sốt v.v… đều là hệ thống phục hồi thân thể của chúng ta đang hoạt động, đừng có quá lạm dụng thuốc khi vừa mới xuất hiện bệnh trạng, nếu không chính thuốc ấy sẽ phá hoại chức năng phục hồi thân thể của bạn, khi mà chức năng phục hồi của bạn bị suy yếu hoặc mất đi, thế thì bạn đã giao vận mệnh của mình cho thuốc rồi. Nên nhớ rằng, nếu bệnh trạng không nghiêm trọng, biện pháp tốt nhất là dưỡng tĩnh, an tâm tĩnh khí có thể khiến hệ thống sữa chữa của bản thân hoàn thành được công tác phục hồi. Cho nên, mỗi một người trong chúng ta cần thận trọng khi dùng thuốc, để cho hệ thống hồi phục chức năng của cơ thể được khôi phục, đây mới chính là đạo chân chính trong việc giữ gìn sức khỏe.
100. Rất nhiều trọng bệnh hoặc bệnh hiểm nghèo, đều chỉ bắt nguồn từ một lý do: Hận. Khi mà cái hận này biết mất, bệnh ắt cũng theo đó mà tiêu trừ. Trong thế gian này điều khó giải quyết nhất chính là hận thù kéo dài, chính vì không hóa giải được cái hận đó, mới có những bệnh không thể trị khỏi được.

[Discovery] Chân thực ảnh động về hoạt động của súng ngắn khi bạn bóp cò

Súng ngắn bán tự động Colt M1911 là một loại súng lục của Mỹ do John Browning thiết kế, sử dụng loại đạn .45 ACP, là súng tiêu chuẩn của quân đội Hoa Kỳ từ năm 1911 đến năm 1985 và hiện này vẫn là một loại vũ khí quân dụng của Hoa Kỳ.

Mới đây, nhà thiết kế Jacob O’Neal của trang Animagraffs.com đã tạo ra một series ảnh động giải thích cách làm việc bên trong của chiếc M1911 này. Mời các bạn cùng theo dõi hoạt động của khẩu súng huyền thoại này.

Tính đến nay thì nó đã được hơn 100 tuổi bởi vì nó đã phục vụ suốt hơn 100 năm trong nhiều quân đội và cuộc chiến khác nhau kể từ năm 1911. Súng này được sử dụng rộng rãi trong Thế chiến thứ nhất, Thế chiến thứ hai, Chiến tranh Triều Tiên và Chiến tranh Việt Nam.

Súng nặng 1105 gam (chưa kể đạn), dài 213 mm, nòng dài 125,7 mm. Hộp tiếp đạn chứa được 8-9 viên. Súng có thể nạp thêm một viên lẻ vào buồng đạn, và tạo hiệu ứng “7 + 1” viên.

Tầm bắn hiệu quả là 62 m, xa hơn các súng ngắn khác 12 mét với độ chính xác phi thường cho một khẩu súng ngắn. Súng còn nổi tiếng vì có một lực cản phi thường (của viên đạn.45 ACP) có thể cản người nặng gần 80 kg chỉ với một viên đạn.

Ngoài ra súng rất dễ lau chùi và bảo quản, dễ và nhanh hơn cả Beretta M9. Súng này tuy nhiên có điểm yếu, là phải được bắn và lau chùi từ khi mới mua, hoặc không thì sẽ bị kẹt.

Tham khảo: businessinsider

[Discovery] Thiên tài Leonardo da Vinci và những bí mật không phải ai cũng biết

Leonardo da Vinci, một thiên tài, một nhà sáng chế vĩ đại trong lịch sử nhân loại, và hơn thế nữa, ông còn là nguồn gốc của rất nhiều bí ẩn cho tới giờ vẫn đang gây nhiều tranh cãi. Tác phẩm Mật mã Da Vinci là một trong những ví dụ nổi tiếng nhất về những huyền thoại và những truyền thuyết xung quanh nhân vật này, tuy nhiên, đó chưa phải là tất cả. Đã vài trăm năm trôi qua kể từ thời kỳ của Da Vinci, và nhiều thứ giờ đây chỉ đơn giản là không thể kiểm chứng được. Hãy cùng Genk điểm qua một số bí ẩn xung quanh nhân vật này trong bài viết dưới đây.

Leonardo – Kẻ dị giáo

Theo nhiều tác giả của các tiểu thuyết lịch sử, Da Vinci là một kẻ dị giáo. Bằng chứng rõ ràng nhất của giả thuyết này có lẽ được ẩn giấu trong tác phẩm Bữa tối cuối cùng, tác phẩm mà nhiều người cho rằng Da Vinci đã tự mình bày tỏ niềm tin vào việc Christ đã kết hôn với Mary Magdalene.  Người phụ nữ này được nhận diện thông qua hình ảnh một tông đồ với những đường nét của một người phụ nữ và ngồi phía bên phải chúa Jesus.

Ngoài ra, cũng có những bằng chứng khác ủng hộ giả thuyết này, đó là việc Da Vinci, vô tình hay cố ý vẽ thiếu đi cốc rượu lễ, biểu tượng của lễ ban thánh thể, cùng với đó là sự hiện diện của một bàn tay kỳ quái – bàn tay không hề thuộc về ai trong bức tranh đang giữ chặt một con dao.

Vậy sự thật là gì? Trên thực tế, bức tranh Bữa tối cuối cùng, bức bích họa vốn được trang hoàng tại tu viện Santa Maria delle Grazie tại Milano, Italy là tác phẩm được Da Vinci lấy cảm hứng từ sách Phúc âm của John, và bản phúc âm này không hề đề cập tới cốc rượu thánh thể hay bất cứ một lễ ban thánh thể nào. Thêm vào đó, bàn tay cầm dao thuộc về Thánh Peter (chi tiết này được làm rõ sau khi bức họa được khôi phục về trạng thái gần với nguyên bản nhất), và dùng để ám chỉ một đoạn trong sách Phúc âm, khi Peter cắt tai một kẻ phụng sự thuộc High Priest.

Và cuối cùng, những chi tiết có phần nữ tính của tông đồ ngồi phía bên phải Jesus có thể được giải thích bằng tính thời đại trong cách ăn mặc – khi những tông đồ trẻ tuổi của Jesus phải để tóc dài và xử sự một cách hiền lành, hòa nhã.

Những biểu tượng bí truyền

Không hẳn là một kẻ dị giáo, nhưng chắc chắn Da Vinci cũng không phải là một người sùng đạo. Rất có khả năng Da Vinci đã được tiếp xúc với những ý tưởng mà tại thời điểm đó được coi là dị giáo, như triết học Platon hay học thuyết Gnostic. Học thuyết Gnostic tôn sùng nữ thần Sophia – biểu tượng của tác phẩm Leda đã thất lạc. Trong một số bản sao chép còn lại, nữ thần này được nhìn thấy như là một “quả trứng khổng lồ”, từ đó sinh ra nhân loại.

Thuyết Gnostic cũng tin vào việc chúa Jesus có hai dạng tồn tại, phần xác thịt đã chết trên thánh giá, và phần còn lại chỉ là linh hồn. Một bức họa nổi tiếng khác của Da Vinci, Virgin of the Rocks cho thấy 2 đứa trẻ rất giống nhau, có lẽ đứa trẻ thường được nhắc đến với cái tên John the Baptist thực ra chính là người anh em song sinh của Jesus, và danh tính của ông đã bị thay đổi nhằm tạo sự chấp thuận trong cộng đồng Thiên chúa giáo. Hoặc có lẽ, 2 đứa trẻ này chỉ là một người duy nhất. Không ai có thể nói chính xác được giả thuyết nào là chính xác nhất.

Da Vinci có phải là thành viên của Tu viện Sion?

Cuốn tiểu thuyết “Mật mã Da Vinci” là một chuyến phiêu lưu dài xung quanh những bí ẩn và truyền thuyết về Tu viện Sion, người lưu giữ những bí ẩn và khám phá của các Hiệp sĩ dòng đền. Dan Brown cũng liên tục đề cập đến việc, nhiều nhân vật nổi tiếng rất có thể là thành viên của hội kín này, ví dụ như Isaac Newton, Victor Hugo, và tất nhiên, Leonardo Da Vinci.

Trên thực tế, tổ chức này được sáng lập ra bởi một người Pháp có tên là Pierre Plantard vào năm 1956. Plantard lấy tên Tu viện Sion dựa trên một ngọn đồi phía trên Annemasse, nơi ông lên kế hoạch dựng lên một nơi ẩn dật. Về bản phả hệ có liên quan đến Chúa Jesus, đây thực chất là bản phả hệ được sao chép lại từ một bản phả hệ khác được tìm thấy vào năm 1915 tại Mỹ bởi Harvey Spencer Lewis, người có quan hệ thân thiết với Plantard. Plantard ra sức củng cố bản phả hệ này nhằm mục đích chứng minh ông là hậu duệ của dòng dõi Merovingian, người thừa kế của một triều đại đã biến mất trong bụi mù lịch sử, từ đó cho ông nhiều lợi thế và cơ hội hơn trên con đường chính trị của mình. Nhưng điều đó đã không trở thành hiện thực.

Kỹ thuật viết phản chiếu

Da Vinci sở hữu một kỹ thuật viết lách khá “dị”: ông thường viết từ phải sang trái và từ trang cuối trở lên. Sự lập dị này thường được phiên giải ra như là một cách sắp đặt riêng của Da Vinci, nhằm biến các khám phá và công trình của ông trở nên bí ẩn và khó hiểu với những người khác. Những người cho ông là dị giáo thì gọi đây là hành vi của quỷ dữ, bởi tính trái ngược dị thường của nó.

Trên thực tế, đây là một cách viết tự phát của Da Vinci. Thần kinh học hiện đại đã cho thấy, đây là một thói quen thường gặp ở những người thuận tay trái, thói quen này sẽ phát sinh trong tầm tuổi thiếu niên, và sẽ duy trì nếu không được sửa chữa – như trong trường hợp của Da Vinci.

Ai mới thực sự là Mona Lisa?

Danh tính của người phụ nữ trong bức ảnh nổi tiếng nhất thế giới, từ lâu đã là chủ đề được đưa ra tranh cãi. Mặc dù các bằng chứng đưa ra chưa rõ ràng, nhưng nhiều tác giả cho rằng, người phụ nữ đó thuộc gia tộc Sforza, có tên là Catherine, hoặc mẹ nàng, Caterina Buti del Vacca, hoặc thậm chí là người chị Bianca. Một số người thì cho rằng, đây là bức tranh tự họa của Da Vinci, khi những phân tích trên máy tính cho thấy nhiều điểm tương đồng giữa 2 khuôn mặt.

Giả thuyết được chấp nhận nhất cho đến nay là người phụ nữ này chính là Lisa Gherardini. Bà là vợ của Francesco del Giocondo (hay Gionconda, trùng với tên gọi khác của bức tranh). Một nghi vấn khác khó xác minh hơn là địa điểm của bức tranh. Cây cầu bên phải dường như khắc họa lại một cây cầu tại Buriano, gần Arezzo, nhưng nhiều khả năng đây chỉ là một khung cảnh được Da Vinci dựng lên nhờ trí tưởng tượng của mình.

Những gì còn sót lại?

Lăng mộ của Da Vinci đã không còn tồn tại, và không ai biết giờ xương cốt của ông đang nằm tại đâu. Sau khi qua đời, ông được chôn tại nhà thờ Saint Florentin tại Amboise, Pháp. Nhưng đến năm 1802, do tác động của thời gian, và đặc biệt là sự phá hủy do cuộc chiến Cách mạng Pháp, nhà thờ này đã bị phá hủy. Gạch và đá từ các lăng mộ , sau đó đã được sử dụng để phục hồi lại nhà thờ, còn các hài cốt được di chuyển tới nhiều địa điểm khác nhau.

Cho đến năm 1863, thi sĩ người Pháp Arsene Houssaye đã tìm ra một bộ hài cốt gần như còn nguyên vẹn, với một cách tay bị uốn cong và một hộp sọ rất lớn. Cách đó không xa, ông cũng phát hiện ra những mảnh vỡ của một phiến đá đã bị xóa mờ gần nửa, với những dòng chữ còn đọc được là EO DUS VINC. Liệu đó có phải tên của Da Vinci trong tiếng Latin, LEONARDUS VINCIUS? Đồng thời, bộ hài cốt này cũng được tìm thấy trong một lâu đài nằm tại Amboise, không xa nơi ông được chôn cất ban đầu.

Có lẽ, điều nghi vấn này, cũng như tất cả các nghi vấn khác xung quanh cuộc đời phi thường của Leonardo Da Vinci, sẽ mãi chỉ là những câu hỏi không có lời giải đáp.

Tham khảo: csicop

[Dev Tip] ASP.NET Web API: Understanding OWIN/Katana Authentication/Authorization Part III: Adding Identity

This is the third post in a series in which we have built up a minimal, self-hosted, OWIN-based Web Api application essentially from scratch. Our objective has been to develop a better understanding of how the various components fir together and interact in an OWIN-based environment, and to do so without creating any dependencies on IIS or the heavy weight System.Web.dll.

Up to this point, we have created a basic Web Api, and implemented our own authentication/authorization, using basic OWIN authorization, and our own set of models. What we have built so far represents a bare-bones model of how authentication and authorization work in an OWIN-based application. We have taken some architectural shortcuts in the name of maintaining a simple, easy to understand structure as again, our goal so far has emphasized concept over details.

Image by alles-schlumpf  |  Some Rights Reserved

Previous posts, in order:

In this post, we are going pull in the ASP.NET Identity framework, and ideally, we will again achieve a better understanding of how Identity fits in to a general Web Api application, and we will allow Identity to perform some of the heavy lifting for us when it comes to difficult, hard-to-get-right-even-for-the-experts details such as crypto and security details.

Source Code for Examples

We are building up a project over a series of posts here. In order that the source for each post make sense, I am setting up branches that illustrate the concepts for each post:

On Github, the branches of the Web Api repo so far look like this:

  • Branch: Master – Always the most current, includes all changes
  • Branch: auth-db The code we build up in the course of the previous post, adding a persistence layer for our authentication system.
  • Branch: auth-identity – the code we will build out in the course of this post. We will start where we left off in the previous post, and modify to bring in a minimal implementation using Identity Framework.

The code for the API client application is in a different repo, and the branches look like this:

  • Branch: Master – Always the most current, includes all changes
  • Branch: owin-auth – Added async methods, and token-based authentication calls to the Web Api application. The code for the client application remains unchanged, except when we need to switch out user credentials.

In the previous article, we created create the classes MyUser and MyUserClaim classes in order to implement our authorization and authentication mechanism in the OWIN/Katana environment, and which also became our code-first models for database persistence via Entity Framework. We also created the MyUserStore class, which contained the methods necessary to save and retreive user authentication data from our backing store.

We had assembled these very rudimentary classes into a functioning authentication and authorization framework of sorts, using them in our application to perform the basic functions needed to properly authenticate a user, and establish a minimal authorization mechanism based upon the role claims possessed by each user.

In this post, we are going to use ASP.NET Identity instead, and replace our crude, homebuilt mechanism with a fully-functioning, if basic, auth system.

Core Identity Framework

To understand how Identity will fit into our application, and the OWIN/Katana environment, it is useful to examine the structure of Identity framework itself.

The actual core Identity library is Microsoft.AspNet.Identity.Core. This library defines a host of interfaces upon which the function of Identity is based, and a smaller number of concrete implementation classes which are expressed in terms of these interfaces. We actually already have this library in our project, because we pulled in theMicrosoft.AspNet.Identity.Owin library previously via Nuget. We haven’t used any of the identity components to this point, but we made use of some items from dependent libraries included in that Nuget package, such as Microsoft.Owin.Security and Microsoft.Owin.OAuth

In general, the models which might need to be consumed in an application are expressed as interfaces, and the internals of the framework provide implementation for those interfaces. It is up to the application, and/or any other frameworks pulled in, to provide the concrete implementations for these model interfaces.

For example, the core Identity framework provides us with a pair of interfaces to represent a User:

Two Versions of the IUser Interface:
// Interface with generic type argument for the Key:
public interface IUser<out TKey>
{
    TKey Id
    {
        get;
    }

    string UserName
    {
        get;
        set;
    }
}


// Interface derived from IUser<Tkey> Specifying string Key:
public interface IUser : IUser<string> { }

In a similar manner, most of the interfaces defined in the core Identity framework to represent persistence models are expressed in a manner which allows us to specify the type for the key to be used.

Additionally, many of the Identity interfaces are dependent on other interfaces in the framework. In these cases, the interface is expressed in terms of a generic type argument representing the concrete implementation of the dependency. For example, core Identity framework provides two interfaces to represent a UserStore:

Two Versions of the IUserStore Interface:
// Interface with generic type arguments for User, and the User Key:
public interface IUserStore<TUser, in TKey> : IDisposable
where TUser : class, IUser<TKey>
{
    Task CreateAsync(TUser user);
    Task DeleteAsync(TUser user);
    Task<TUser> FindByIdAsync(TKey userId);
    Task<TUser> FindByNameAsync(string userName);
    Task UpdateAsync(TUser user);
}


// Interface expressing IUserStore in terms of generic User type, 
// and specifying a string User Key
public interface IUserStore<TUser> : IUserStore<TUser, string>, IDisposable
where TUser : class, IUser<string>
{

}

If you explore the Microsoft.AspNet.Identity.Core library using a free tool such as Telerik’s fine Just Decompile, you can explore the various interfaces and concrete classes available, and develop an understanding of how they relate. However, a quick look using even the VS Object Browser will reveal that there are no concrete implementations of the basic model interfaces we need in order to implement Identity in our application. For this, we either need to roll our own, or pull in another library which provides ready-to-use implementations.

Since we are already using Entity Framework, in our case this is easy.

Identity and Entity Framework

The Microsoft.AspNet.Identity.EntityFramework library provides concrete implementation classes needed to use Identity from an application using Entity Framework. In this library we find some model classes we can use as-is, or which we can extend and customize as needed. For example, the IdentityUser class provides a concrete implementation for IUser<Tkey> :

The Base IdentityUser Class:
// Base implements IUser<TKey> and is expressed with generic type arguments
// for other model types required by Identity Framework:
public class IdentityUser<TKey, TLogin, TRole, TClaim> : IUser<TKey>
    where TLogin : IdentityUserLogin<TKey>
    where TRole : IdentityUserRole<TKey>
    where TClaim : IdentityUserClaim<TKey>
{
    public IdentityUser()
    {
        this.Claims = new List<TClaim>();
        this.Roles = new List<TRole>();
        this.Logins = new List<TLogin>();
    }

    public virtual TKey Id { get; set; }
    public virtual string UserName { get; set; }
    public virtual string Email { get; set; }
    public virtual bool EmailConfirmed { get; set; }
    public virtual string PhoneNumber { get; set; }
    public virtual bool PhoneNumberConfirmed { get; set; }

    public virtual string SecurityStamp { get; set; }
    public virtual bool TwoFactorEnabled { get; set; }
    public virtual string PasswordHash { get; set; }

    public virtual int AccessFailedCount { get; set; }
    public virtual bool LockoutEnabled { get; set; }
    public virtual DateTime? LockoutEndDateUtc { get; set; }

    public ICollection<TLogin> Logins { get; set; }
    public ICollection<TRole> Roles { get; set; }
    public ICollection<TClaim> Claims { get; set; }
}


// Alternate implementation derives from Generic implementation, 
// and expresses Generic model types in terms of classes defined 
// within Identity.EntityFrameowrk Library: 
public class IdentityUser : IdentityUser<string, IdentityUserLogin, 
    IdentityUserRole, IdentityUserClaim>, IUser, IUser<string>
{
    public IdentityUser()
    {
        this.Id = Guid.NewGuid().ToString();
    }

    public IdentityUser(string userName) : this()
    {
        this.UserName = userName;
    }
}

We can see in the above example that there is a lot of functionality ready to go in the basic IdentityUserimplementation. Also, note that the various generic type arguments provided in the base implementation are again provided such that we might extend our Identity model classes with custom implementations, for example, if we wanted to use integer keys instead of strings.

The Identity.EntityFramework library provides similar implementations for the other interfaces defined in Identity.Core. In addition, as we might expect, Identity.EntityFramework also includes theIdentityDbContext class, which knits together the various model classes, ready for use in a EF/Code-First application.

What is important here is understanding that the Identity.Core library provides the interfaces we need, and implements the interactions between those interfaces. It is up to us to provide the implementation for those interfaces, either by rolling our own, or by using a library specific to our persistence model such asIdentity.EntityFramework.

Add Identity.EntityFramework Library Via Nuget

Since we are using Entity Framework in our minimal OWIN Web Api project, we will pull in theIdentity.EntityFramework package we discussed above to take advantage of the ready-made Identity implementation afforded by the Identity team.

NOTE: This post assumes you are working with ASP.NET < 5.0, and Identity 2.1. As of this publication date, the newest package for this library is a pre-release of Identity 3.0 which targets ASP.NET 5. Unless you are working with ASP.NET 5.0 (“vNext”) you want to make sure you are pulling in version 2.1

Add the Microsoft.AspNet.Identity.EntityFramework Nuget Package:
PM> Install-Package Microsoft.AspNet.Identity.EntityFramework -Version 2.1.0

We already have the Identity.Core library in our example project, because it was included when we pulled in theIdentity.Owin Nuget package in Part I of this series.

Add Identity to the Self-Hosted Web Api – Models and Stores

To get started, we will be picking up where we left off in the previous post. Recall that we had added anAuthModels.cs file, and coded up a MyUser class, a MyUserClaim class, a MyPasswordHasher class, and aMyUserStore class.

We can get rid of all that now, delete the AuthModels.cs file.

In order to add the (mostly) ready-to-use Identity framework to our project, let’s add a new code file namedIdentityModels.cs, and add the following code:

Add Identity Models:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

// Add using statements:
using Microsoft.Owin;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.AspNet.Identity.EntityFramework;

namespace MinimalOwinWebApiSelfHost.Models
{
    public class ApplicationUser : IdentityUser
    {
        // A default Constructor:
        public ApplicationUser() { }

        public ApplicationUser(string email) : base(email)
        {
            // Use the email for both user name AND email:
            UserName = email;
        }
    }


    public class ApplicationUserManager 
        : UserManager<ApplicationUser>
    {
        public ApplicationUserManager(IUserStore<ApplicationUser> store) 
            : base(store) { }


        public static ApplicationUserManager Create(
            IdentityFactoryOptions<ApplicationUserManager> options,
            IOwinContext context)
        {
            return new ApplicationUserManager(
                new UserStore<ApplicationUser>(
                    context.Get<ApplicationDbContext>()));
        }
    }
}

Now, let’s take a good hard look at what’s going on in the above code.

First, we have added an ApplicationUser class, which derives from IdentityUser. IdentityUser is a concrete implementation if the Identity.Core IUser interface, and is provided by theIdentity.EntityFramework library we discussed previously. We aren’t doing much in this derived class at this point, but we will be adding to it later.

Next, we have the ApplicationUserManager class, which derives from UserManager. Unlike IdentityUser, the UserManager class is a part of the Identity.Core library. In other words, any application using the Identity framework can expect to have access to UserManager, or a derivation similar to what we have done above.

Notice that our ApplicationUserManager expects an argument of IUserStore as a constructor parameter. What’s this?

We’ll take a short detour to discuss UserManager and UserStore, and the purpose behind each.

UserManager and UserStore – What’s the Difference?

The core Identity framework defines the UserManager class to implement various functionality required to, well, manage user information according to business rules and configuration established either by Identity framework itself, or as part of configuration options set up during development.

These framework “rules” and configuration items are independent of the specific persistence store used to save and retrieve the user identity data. In other words, the UserManager understands and works with Identity model objects, without concern for the concrete database underlying the application.

Examples of the sorts of functionality afforded by UserManager include methods such as:

  • CreateAsync(TUser user, string Password)
  • AddToRoleAsync(TKey userId, string role)
  • AddClaimAsync(Tkey userId, Claim claim)

The UserManager class is defined in terms of various interfaces which represent abstractions over database-specific implementation models. As an example, the basic UserManager is defined with a generic type argument for the IUser implementation, which must be specified. The UserManager class also requires a constructor argument which implements the IUserStore interface.

A concrete implementation of IUserStore represents the underlying persistence layer of the application. In other words, a UserStore implementation knows how to “talk” to a specific data store (such as MongoDb, SQL Server, RavenDb, Etc.).

In our code, we are using the default UserStore implementation provided by EntityFramework (which is, itself, an abstraction over our SQL CE or SQL Server database…).

The idea behind defining a UserManager base class in Identity.Core in terms of an interface IUserStore is to achieve a clean separation between the business rules governing how authentication and authorization occurs between Identity model objects, and the details of the application’s specific backing store.

Within out application proper, when we use Identity we should generally be using the UserManager (or a derived version of it) the work directly with our identity model objects. We rarely have need to consume an instance ofUserStore directly, except for the purpose of injecting it as a constructor argument to UserManager.

UserManager, UserStore, and Identity:

usermanager-userstore

Also notice in our code, we have added a static method, Create(). We’ll discuss this momentarily as well. But first, we will update the code for our database context.

Update the DbContext to Inherit from IdentityDbContext

When we finished the last article in this series, we had updated our ApplicationDbContext code file to look like this:

The Previous DbContext:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

// Add using:
using System.Data.Entity;
using System.Security.Claims;

namespace MinimalOwinWebApiSelfHost.Models
{
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext()
            : base("MyDatabase")
        {

        }

        static ApplicationDbContext()
        {
            Database.SetInitializer(new ApplicationDbInitializer());
        }

        public IDbSet<Company> Companies { get; set; }
        public IDbSet<MyUser> Users { get; set; }
        public IDbSet<MyUserClaim> Claims { get; set; }
    }


    public class ApplicationDbInitializer 
        : DropCreateDatabaseAlways<ApplicationDbContext>
    {
        protected async override void Seed(ApplicationDbContext context)
        {
            context.Companies.Add(new Company { Name = "Microsoft" });
            context.Companies.Add(new Company { Name = "Apple" });
            context.Companies.Add(new Company { Name = "Google" });
            context.SaveChanges();

            // Set up two initial users with different role claims:
            var john = new MyUser { Email = "john@example.com" };
            var jimi = new MyUser { Email = "jimi@Example.com" };

            john.Claims.Add(new MyUserClaim 
            { 
                ClaimType = ClaimTypes.Name, 
                UserId = john.Id, 
                ClaimValue = john.Email 
            });

            john.Claims.Add(new MyUserClaim 
            { 
                ClaimType = ClaimTypes.Role, 
                UserId = john.Id, 
                ClaimValue = "Admin" 
            });

            jimi.Claims.Add(new MyUserClaim 
            { 
                ClaimType = ClaimTypes.Name, 
                UserId = jimi.Id, 
                ClaimValue = jimi.Email 
            });

            jimi.Claims.Add(new MyUserClaim 
            { 
                ClaimType = ClaimTypes.Role, 
                UserId = john.Id, 
                ClaimValue = "User" 
            });

            var store = new MyUserStore(context);
            await store.AddUserAsync(john, "JohnsPassword");
            await store.AddUserAsync(jimi, "JimisPassword");
        }
    }
}

In the same code file, we had defined both our ApplicationDbContext, and a database initializer.

Now that we have access to the Identity.Core and Identity.EntityFramework libraries, we can simplify this somewhat.

First of all, Identity.EntityFramework provides us with IdentityDbContext, which, as its name implies, is an Identity-specific implementation of the DbContext. There is a little more going on under the hood than we will cover here, but essentially, IdentityDbContext provides us with a base class from which we can inherit, and which provides a DbContext implementation which works with the base Identity.EntityFramework models we will be working with.

First, we are going to modify the code for our ApplicationDbContext above to derive fromIdentityDbContext. Then, we will update the ApplicationDbInitializer to work with our new DbContextand Identity models.

Modify DbContext to Derive from IdentityDbContext:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

// Add using:
using System.Data.Entity;
using System.Security.Claims;

// Add THESE to use Identity and Entity Framework:
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;

namespace MinimalOwinWebApiSelfHost.Models
{
    // Derive from IdentityDbContext:
    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext()
            : base("MyDatabase") { }


        static ApplicationDbContext()
        {
            Database.SetInitializer(
                new ApplicationDbInitializer());
        }


        // Add a static Create() method:
        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }


        // We still need a DbSet for our Companies 
        // (and any other domain objects):
        public IDbSet<Company> Companies { get; set; }
    }


    public class ApplicationDbInitializer 
        : DropCreateDatabaseAlways<ApplicationDbContext>
    {
        protected async override void Seed(ApplicationDbContext context)
        {
            context.Companies.Add(new Company { Name = "Microsoft" });
            context.Companies.Add(new Company { Name = "Apple" });
            context.Companies.Add(new Company { Name = "Google" });
            context.SaveChanges();

            // Set up two initial users with different role claims:
            var john = new ApplicationUser 
            { 
                Email = "john@example.com", 
                UserName = "john@example.com" 
            };
            var jimi = new ApplicationUser 
            { 
                Email = "jimi@Example.com", 
                UserName = "jimi@example.com" 
            };

            // Introducing...the UserManager:
            var manager = new UserManager<ApplicationUser>(
                new UserStore<ApplicationUser>(context));

            var result1 = await manager.CreateAsync(john, "JohnsPassword");
            var result2 = await manager.CreateAsync(jimi, "JimisPassword");

            // Add claims for user #1:
            await manager.AddClaimAsync(john.Id, 
                new Claim(ClaimTypes.Name, "john@example.com"));

            await manager.AddClaimAsync(john.Id, 
                new Claim(ClaimTypes.Role, "Admin"));

            // Add claims for User #2:
            await manager.AddClaimAsync(jimi.Id, 
                new Claim(ClaimTypes.Name, "jimi@example.com"));

            await manager.AddClaimAsync(jimi.Id, 
                new Claim(ClaimTypes.Role, "User"));
        }
    }
}

In the above code, notice that we have now implemented our ApplicationDbContext by deriving fromIdentityDbContext<ApplicationUser> . In so doing, we have specified a DbContext implementation which will be ready to use, and already work with our ApplicationUser class.

We have also updated our ApplicationDbInitializer, making use of the handy interface afforded by ourApplicationUserManager to easily add our test users, and related user claims.

Pay close attention here. Remember previously, how we went ahead and create a mock password hasher, and all that nonsense about implementing a proper crypto mechanism for hashing passwords? here, Identity has taken care of all that for us. No mocking needed. Just the way we like it, we have left the details of the crypto to folks who know what they are doing. Remember, crypto is hard, even for the experts, and it is a solved problem.

Now, before we go much further, we are going to take another short detour. Notice how, like we did withApplicationUserManager, we also defined a static Create() method on our ApplicationDbContext? We’re going to take a look at why we did that now.

Context per Request and CreatePerOwinContext

From the standpoint of our data model, we want to make sure that we are always working with the same instance of our database context, and hence, with the same set of objects. For example, if two separate instances ofApplicationDbContext (or, similarly, UserStore or UserManager) are created while processing the same HTTP request, it is possible we could introduce changes to two instances of the same  user data.

We want to make sure that when we retreive a user object, it will always refer to the same instance of that user’s data within the context of a single HTTP request.

The Microsoft.AspNet.Identity.Owin library provides an extension method by which we can ensure a single instance of an object is created per OwinContext. The CreatePerOwinContext() method allows us to pass in a generic type argument, and a function reference which returns an instance of the desired object. We set this up during the Owin Configuration() method. Then, when the OwinContext object is created for each incoming HTTP request, a discreet instance of the desired object will be created per OWIN context.

For a deeper look at this concept, see Per request lifetime management for UserManager class in ASP.NET Identity

In our application, we want to make sure that during request processing, we are only ever working against the same instance of ApplicationDbContext, as well as ApplicationUserManager. We achieve this by adding those state Create() methods on ApplicationDbContext and ApplicationUserManager respectively, and then passing references to them to CreatePerOwinContext() during the Owin Configuration() method.

We will want to add the following code to our ConfigureAuth() method in our Startup class:

Create ApplicationDbContext and ApplicationUserManager per Owin Context:
private void ConfigureAuth(IAppBuilder app)
{
    // Create per OWIN Context:
    app.CreatePerOwinContext<ApplicationDbContext>(ApplicationDbContext.Create);
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

    var OAuthOptions = new OAuthAuthorizationServerOptions
    {
        TokenEndpointPath = new PathString("/Token"),
        Provider = new ApplicationOAuthServerProvider(),
        AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),

        // Only do this for demo!!
        AllowInsecureHttp = true
    };
    app.UseOAuthAuthorizationServer(OAuthOptions);
    app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

Recall from our previous explorations of OWIN and Katana that when we pass function references like this, the function itself is not executed at this point in our code. Instead, a reference to the function is added to the Owin Environment Dictionary, which will then be Invoked each time a new Owin context is created in response to an incoming HTTP request.

We can see some of the logic to all this if we take a closer look at the static Create() method we defined on ourApplicationUserManager class:

The Create() Method from ApplicationUserManager:
public static ApplicationUserManager Create(
    IdentityFactoryOptions<ApplicationUserManager> options,
    IOwinContext context)
{
    return new ApplicationUserManager(
        new UserStore<ApplicationUser>(
            context.Get<ApplicationDbContext>()));
}

Notice how even here, we are initializing an instance of UserStore and passing in a reference toApplicationDbContext by retrieving it from the OwinContext instance? This way we ensure that even here, we are using the single DbContext object instance created specifically for each request.

Update OAuth Server Provider for Identity

Now that we have implemented a very basic Identity model, we can modify ourApplicationOauthServerProvider. In the call to GrantResourceOwnerCredentials(), we can avail ourselves of our ApplicationUserManager and Identity models to simplify the grant process.

Add Microsoft.AspNet.Identity.Owin to the using statements at the top of the file, and then replace the existing code as follows:

Update the code for GrantResourceOwnerCredentials for Identity:
using System.Threading.Tasks;

// Add Usings:
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.OAuth;
using System.Security.Claims;
using MinimalOwinWebApiSelfHost.Models;

// Add to use Identity:
using Microsoft.AspNet.Identity.Owin;

namespace MinimalOwinWebApiSelfHost.OAuthServerProvider
{
    public class ApplicationOAuthServerProvider 
        : OAuthAuthorizationServerProvider
    {
        public override async Task ValidateClientAuthentication(
            OAuthValidateClientAuthenticationContext context)
        {
            // This call is required...
            // but we're not using client authentication, so validate and move on...
            await Task.FromResult(context.Validated());
        }


        public override async Task GrantResourceOwnerCredentials(
            OAuthGrantResourceOwnerCredentialsContext context)
        {
            // ** Use extension method to get a reference 
            // to the user manager from the Owin Context:
            var manager = context.OwinContext.GetUserManager<ApplicationUserManager>();

            // UserManager allows us to retrieve use with name/password combo:
            var user = await manager.FindAsync(context.UserName, context.Password);
            if (user == null)
            {
                context.SetError(
                    "invalid_grant", "The user name or password is incorrect.");
                context.Rejected();
                return;
            }

            // Add claims associated with this user to the ClaimsIdentity object:
            var identity = new ClaimsIdentity(context.Options.AuthenticationType);
            foreach (var userClaim in user.Claims)
            {
                identity.AddClaim(new Claim(userClaim.ClaimType, userClaim.ClaimValue));
            }

            context.Validated(identity);
        }
    }
}

Once again, see in the above how we made sure to grab a reference to the ApplicationUserManager instance from the context object? The context object helpfully provides a GetUserManager() extension method.

Also note how the ApplicationUserManager makes it very convenient to retrieve a user object with a user name and password. If the password fails to match, null will be returned, and the invalid grant error returned.

Update the CompaniesController to Use the DbContext per Request

We don’t HAVE to do this, but we can. We might update our CompaniesController to take advantage of the Context-per-Request strategy afforded by Identity here.

Make sure to add Microsoft.AspNet.Identity.Owin to the using statements at the top of theCompaniesController file.

Update CompaniesController to Use Context per Request:
public class CompaniesController : ApiController
{
    // Ditch THIS:
    //ApplicationDbContext dbContext = new ApplicationDbContext();

    // Replace with something like THIS:
    ApplicationDbContext dbContext
    {
        get
        {
            return Request.GetOwinContext().Get<ApplicationDbContext>();
        }
    }

    ... All the rest of the controller code....

}

With that, we can give our new and improved application a test run, using the same Api Client application from our previous post.

Running the Application with Identity in Place

If we spin up our Web Api, all should look well:

Running the Web Api Application – All is Well:

run-web-api-application

Next, if we run the API Client application, making sure we use our valid user credentials (they should match the credentials for the Admin user in the Seed() method), everything should work as before:

Running the API Client Application:

run-api-client-application-with-identity

Similarly, if we modify the code in our client application and pass an invalid password, we get an invalid grant error:

Invalid Password Submitted by Client Returns Invalid Grant Error:

run-api-client-application-with-identity-invalid-grant

And, if we change the client credentials to those of the user in the plain old User role (which does NOT have authorization to access our CompaniesController), we receive a 401/Unauthorized error:

API Client with Insufficient Authorization:

run-api-client-application-with-identity-unauthorized

Summing it Up

In the course of the last four articles, we have hopefully developed a better idea of how the pieces fit together in an OWIN-based Web Api application. The lines between the various frameworks become blurry as an application grows, and my objective was to break things down in a manner that would bring some clarity to what happens where, and why.

The structure of our example application is crude, and if you were to take this a few steps further, you would definitely want to change some things, do some refactoring, and implement a great deal more exception and error handling.

Similarly, our console-based API Client application is sufficient only to the task of exercising our Web Api for demonstration purposes.

From here, we could go a long ways further in developing a claims-based authorization model. As it stands, our little sample application does use claims, but relies on the in-build ability of [Authorize] attribute to perform a role-based authorization check. We will explore claims more extensively in an upcoming post.

As always, feedback is most welcome, especially if you noticed me doing something stupid, or find outright errors in the code. Pull Requests are welcome against the sample repo, so long as they address improvements or bug fixes. For obvious reasons, I want to keep the code samples in sync with the articles.

REF: http://typecastexception.com/post/2015/02/15/ASPNET-Web-API-Understanding-OWINKatana-AuthenticationAuthorization-Part-III-Adding-Identity.aspx

[Dev Tip] How To Use Unity Container In ASP.NET

Building The Container
The first thing to do is to build the Unity container.
We would like to have a persistent container that hold it’s state
during the running of the application. The right place to put the
is as part of the Global.asax file as a property of the current
running application.
First build an interface for the container property:

public interface IContainerAccessor
{
IUnityContainer Container { get; }
}

After the building of the interface implement it in the Global
class in the Global.asax file:

public class Global : HttpApplication, IContainerAccessor
{
private static IUnityContainer _container;
public static IUnityContainer Container
{
get
{
return _container;
}
set
{
_container = value;
}
}

IUnityContainer IContainerAccessor.Container
{
get
{
return Container;
}
}

protected void Application_Start(object sender, EventArgs e)
{
BuildContainer();
}

protected void Application_End(object sender, EventArgs e)
{
CleanUp();
}

private static void BuildContainer()
{
IUnityContainer container = new UnityContainer();
// Register the relevant types for the
// container here through classes or configuration
// register the container in the container property
Container = container;
}

private static void CleanUp()
{
if (Container != null)
{
Container.Dispose();
}
}
}

In the implementation you hold a static container variable which
will be available in the web application through the interface we build.
In the BuildContainer method we do all the work of registering types
and instances to the Unity container. It can be done by code or
by configuration this decision is yours.

How To Inject Dependencies
After you set up your container it’s time to use it. It is done
by building a base page for all the pages in your application.
The injection of dependencies should be done very early in the
page life cycle and therefore implemented in the OnPreInit event.
The base page class can look like:

public abstract class BasePage<T> : Page where T : class
{
protected override void  OnPreInit(EventArgs e)
{
InjectDependencies();
base.OnPreInit(e);
}

protected virtual void InjectDependencies()
{
var context = HttpContext.Current;
if (context == null)
{
return;
}

var accessor = context.ApplicationInstance as IContainerAccessor;
if (accessor == null)
{
return;
}

var container = accessor.Container;
if (container == null)
{
throw new InvalidOperationException(“No Unity container found”);
}
container.BuildUp(this as T);
}
}

All the checks in the InjectDependencies method are
a guarantee that we have a Unity container. The only interesting
part here is the BuildUp method in the end of the method.
The BuildUp method will ensure that the injection will happen as
required.

Example Of Concrete Page
After building the base page the only thing to do next is to
implement the other pages and inheriting from the base page.
The next example shows how to use the previous BasePage class:

public partial class _Default : BasePage<_Default>
{
[Dependency]
private ILogger Logger { set; get; }

protected void Page_Load(object sender, EventArgs e)
{
Logger.Log(“Something”);
}
}

[Discovery] 10 bí ẩn trong hệ Mặt Trời mà các nhà khoa học vẫn chưa thế lý giải

Mặc dù ngành khoa học vũ trụ đã có nhiều bước tiến mới, cùng với sự hỗ trợ của công nghệ tiên tiến nhưng vẫn còn đó những điều bí ẩn mà chúng ta chưa thể lý giải được. Không phải đâu xa mà ngay trong hệ Mặt Trời của chúng ta cũng vẫn có rất nhiều điều bí ẩn.

1. Tấm lá chắn vô hình xung quanh Trái đất

Năm 1958, James Van Allen tại đại học Iowa đã phát hiện một cặp vành đai bức xạ xung quanh Trái đất, ở khoảng cách 40.000km so với mặt đất. Các vành đai này chứa các hạt điện tử năng lượng cao và proton. Đây chính là các hạt năng lượng bắn ra từ hoạt động của Mặt Trời, vào những lúc Mặt Trời hoạt động mạnh hay còn gọi là hiện tượng bão Mặt Trời thì số lượng cũng như mức độ năng lượng của các hạt này càng tăng cao.

01

Các hạt năng lượng cao cùng bức xạ này chính là những kẻ giết người vô hình, không những vậy chúng còn có thể gây ảnh hưởng tới các vệ tinh và hệ thống điện tử trên Trái đất. Tuy nhiên hấu hết chúng đều không thể tiếp cận bề mặt Trái đất, một số hạt năng lượng cao hơn có thể xâm nhập sâu hơn bầu khí quyển, nhưng tất cả đều phải dừng lại ở khoảng cách 11.000km so với mặt đất.

Các nhà khoa học cho rằng có một bức tường vô hình giúp ngăn cản những hạt năng lượng này xâm nhập vào Trái đất. Nó giống như tấm lá chắn năng lượng vô hình trong các bộ phim viễn tưởng như Star Wars. Tuy nhiên vì sao Trái đất lại có một tấm lá chắn như vậy vẫn là điều bí ẩn chưa có lời giải đáp. Nhiều giả thuyết cho rằng từ trường của Trái đất là nguyên nhân các hạt năng lượng cao không thể xâm nhập vào bên trong, tuy nhiên giả thuyết này vẫn vấp phải nhiều ý kiến phản đối.

2. Hiện tượng bay ngang bất thường

Từ khi con người biết đưa các vệ tinh và tàu vũ trụ vào không gian, các nhà khoa học đã biết tận dụng lực hấp dẫn của các hành tinh giống nhu lực ly tâm để giúp tạo thêm lực đẩy cho những cuộc thám hiểm vũ trụ. Nó gần giống như khi bạn cột một sợi dây vào tảng đá, sau đó quay tròn để ném tảng đá đi xa hơn.

02

Tuy nhiên trong những lần áp dụng phương pháp này, các nhà khoa học nhận thấy một hiện tượng kỳ lạ. Đó là vận tốc quay của tàu vũ trụ hoặc vệ tinh xung quanh một hành tinh là không ổn định. Nó được gọi là hiện tượng bay ngang bất thường. Trong khi đó, trên lý thuyết thì vận tốc quay phải tăng dần hoặc giảm dần với gia tốc ổn định theo như tính toán của các nhà khoa học.

Còn trong thực tế thì tàu vũ trụ Cassini của NASA được phóng lên quỹ đạo của Trái đất vào năm 1999, lại có lúc tăng tốc và có lúc giảm tốc bất thường khi quay xung quanh Trái đất. Nhiều giả thuyết được đặt ra, trong đó có giả thuyết về vật chất tối còn xót lại trong hệ Mặt Trời. Nó giống như một vùng vật chất dày đặc nhưng không thể quan sát được. Khi tàu vũ trụ đi qua vùng vật chất này nó sẽ bị giảm tốc độ lại giống như một viên đạn đang bay từ môi trường không khí sang môi trường chất lỏng.

3. Vệt đỏ lớn trên sao Mộc

Trong lần đầu tiên quan sát sao Mộc, các nhà khoa học đã phát hiện ra một vệt đỏ lớn bí ẩn có hình tròn trên bầu khí quyển của hành tinh này. Kích thước của nó là đủ để 2 Trái đất chui vào, và nó vẫn tiếp tục di chuyển phía trên bầu khí quyển của sao Mộc. Cho đến nay các nhà khoa học vẫn chưa thể biết được nó là cái gì, nhưng chỉ biết rằng nó đã xuất hiện từ cách đây rất lâu rồi.

03

Đã có nhiều giả thuyết đặt ra nhằm giải thích xem nó là cái gì, cũng như sự hình thành và vì sao nó lại có kích thước lớn đến như thế cùng màu đỏ như gạch. Trong đó, nhiều nhà khoa học cho rằng đó là một cơn bão khổng lồ, nó được hình thành từ cách đây rất lâu và trên đường đi của mình nó hấp thụ các cơn bão nhỏ khác. Giống như một hố đen mini để tiếp tục tồn tại và lớn dần lên.

Màu đỏ của cơn bão là do các vật chất trên bề mặt của sao Mộc bị hút vào cơn bão. Tuy nhiên có giả thuyết khác cho rằng ánh sáng Mặt Trời phản chiếu cùng với một số hóa chất có trong khí quyển sao Mộc như amoniac và acetylene khiến cho nó có màu đỏ. Hiện tại thì vệt đỏ bí ẩn này vẫn tiếp tục di chuyển và lớn dần lên.

4. Thời tiết trên mặt trăng Titan của sao Thổ

Titan là Mặt trăng duy nhất của sao Thổ, điều thú vị là nó cũng có các mùa giống như Trái đất. Mỗi mùa trên Titan kéo dài khoảng 7 năm trên Trái đất, đó là vì sao thổ phải mất tới 29 năm để quay xong 1 vòng quanh Mặt Trời. Lần chuyển mùa gần đây nhất trên Titan là vào năm 2009, khi mà Bán cầu Bắc mùa đông chuyển sang mùa xuân và Bán cầu Nam vừa kết thúc mùa hè.

04

Tuy nhiên vào khoảng tháng 5 năm 2012, trong suốt mùa thu ở Nam bán Cầu của Titan, các nhà khoa học phát hiện hình ảnh của một cơn lốc xoáy cực lớn với đường kính lên đến 300km. Đây là điều không thể xảy ra trong điều kiện ấm áp tại Nam bán Cầu lúc đó.

Trong khi đó, bằng phương pháp phân tích quang phổ, các nhà khoa học phát hiện dấu hiệu của các hạt đông lạnh hydrogen cyanide (HCN) bên trong khi quyển của cơn bão này. Trong khi đó để hình thành được các các hạt đông lạnh HCN này thì nhiệt độ phải thấp hơn 100 độ C so với bình thường. Điều đó có nghĩa là thời tiết trên Titan đã có sự đảo chiều khó hiểu.

Hiện tại các nhà khoa học chưa thể lý giải được bí ẩn này. Cũng không có một giả thuyết nào được đặt ra, vì số lượng các hành tinh có sự phân bố mùa giống Trái đất là rất hiếm. Trong khi đó hiện tượng này cũng vô cùng đặc biệt. Nó khiến các nhà khoa học lo sợ điều tương tự có thể xảy ra đối với Trái đất.

5. Tia vũ trụ siêu năng lương cao

Tia vũ trụ với bức xạ năng lượng cao mà không giống như những tia bức xạ từ Mặt Trời là một trong những điều bí ẩn các nhà khoa học vẫn đang nghiên cứu. Cho đến nay chúng ta vẫn chưa biết được các tia vũ trụ này có nguồn gốc từ đâu, cũng như vì sao chúng lại có năng lượng lớn như vậy.

05

Trên Trái đất, các nhà khoa học cũng ghi nhận được những tia vũ trụ như vậy chiếu thẳng vào bầu khí quyển của chúng ta. Nhưng nhờ có tấm lá chắn vô hình mà các tia này không làm ảnh hưởng gì đến con người cũng như các thiết bị điện tử trên bề mặt Trái đất. Các tia vũ trụ này mang theo những hạt năng lượng cao nhất mà chúng ta từng thấy trong vũ trụ.

Có giả thuyết cho rằng các tia vũ trụ này đến từ những vụ nổ rất lớn do sự hình thành, sụp đổ hoặc va chạm của các ngôi sao lớn bên ngoài dải Ngân hà. Tuy nhiên theo quan sát thì sự xuất hiện của các tia vũ trụ này không trùng hợp với bất kỳ hiện tượng vũ trụ nào mà chúng ta có thể quan sát.

6. Hố đen có thể ngăn cản sự hình thành của các ngôi sao

Các nhà khoa học đã phát hiện ra rằng, trong những thiên hà lâu đời thì một hố đen khổng lồ có thể ngăn cản sự hình thành của những ngôi sao trẻ. Những ngôi sao trẻ trong quá trình bắt đầu hình thành sẽ hút những dòng bụi khí trong vũ trụ vào trung tâm của nó với vận tốc rất lớn. Sau đó sẽ có một quá trình nguội lạnh và dòng bụi khí này được ngưng tụ để tạo thành một ngôi sao mới.

06

Tuy nhiên theo như phát hiện mới đây, các nhà khoa học dự đoán rằng một hố đen khổng lồ có thể làm ảnh hưởng đến quá trình này. Họ thấy rằng trong một số thiên hà đỏ, chỉ có những ngôi sao già tồn tại mà không có ngôi sao trẻ nào mới được hình thành.

Theo như những kết quả nghiên cứu khác, các nhà khoa học cho rằng đây có thể là kết quả của một vụ va chạm giữa hai hố đen tại trung tâm của hai dải thiên hà khác nhau. Vụ va chạm đã tạo ra một vụ nổ lớn khiến cho các dòng khí bụi tồn tại trong thiên hà bị văng ra rất xa, khiến cho sau đó nó không còn nguyên liệu để hình thành những ngôi sao mới. Bên cạnh đó cũng có nhiều ý kiến cho rằng lực hấp dẫn rất lớn của hố đen khiến cho dòng bụi khí không thể tập trung để hình thành những ngôi sao (trong những thiên hà có kích thước nhỏ).

7. Khối lượng hố đen lớn hơn rất nhiều so với những gì chúng ta từng nghĩ

Các nhà khoa học tin rằng khối lượng của các hố đen khổng lồ tại trung tâm các thiên hà có khối lượng lớn hơn rất nhiều so với những tính toán trước đây, có thể lớn hơn gấp 40%. Thông qua việc quan sát và nghiên cứu hố đen được mệnh danh là “Eye of Sauron”, các nhà khoa học càng khẳng định được niềm tin trên.

07

Sở dĩ được gọi là Eye of Sauron là vì hố đen này có một đĩa bụi khổng lồ xung quanh khiến cho nó rất giống với hình dạng của con mắt Sauron trong bộ phim Lord of the Rings. Hố đen này nằm ở giữa thiên hà NGC 4151. Các nhà khoa học đã tính toán khoảng cách từ hố đen nay đến Trái đất là khoảng 13-95 triệu năm ánh sáng.

Tuy nhiên với một kỹ thuật hoàn toàn mới, các nhà khoa học đã có thể đo chính xác tới 95% khoảng cách từ Trái đất đến hố đen Eye of Sauron là khoảng 62 triệu năm ánh sáng. Nhờ kỹ thuật mới này đã giúp họ tính toán khối lượng của hố đen một cách chính xác hơn và theo như kết quả thu được thì con số đó lớn hơn gấp nhiều lần những gì chúng ta vẫn tin trước đó.

8. Bản chất lực hấp dẫn của hố đen

Cho đến nay, nhiều nhà khoa học vẫn tin rằng lực hấp dẫn không-thời gian là ổn định và không thể hỗn loạn. Tuy nhiên theo một nghiên cứu mới đây của 3 nhà khoa học Canada thì trường hấp dẫn có tính chất giống như chất lỏng. Nó là hỗn loạn, giống như một xoáy nước.

Lý thuyết này giúp giải thích sự hình thành những đĩa bụi hình xoáy ốc khi bị hút vào hố đen, tuy nhiên nó cũng mở ra một điều thắc mắc cũng như tò mò của nhiều người, đó là ở trung tâm của hố đen có lực hấp dẫn hay không. Nếu giống như một xoáy nước, nghĩa là bất vì vật chất nào tiếp xúc vào bên cạnh của hố đen sẽ bị nó nuốt chửng. Tuy nhiên nếu đi theo chiều vuông góc vào thẳng trung tâm của hố đen thì có thể sẽ không bị tác động của lực hấp dẫn.

Tuy nhiên đây mới chỉ là lý thuyết, các nhà khoa học vẫn còn phải tiến hành thêm nhiều nghiên cứu, có thể là thử nghiệm thực tế bằng phương pháp dò sóng hấp dẫn. Giống như việc đo gió trong những cơn bão, bằng cách gửi những tàu thám hiểm tiếp cận hố đen. Mặc dù vậy khoảng cách từ Trái đất đến các hố đen là rất xa, do đó sẽ còn rất lâu nữa chúng ta mới có thể khám phá hết những điều bí ẩn xung quanh hố đen.

9. Sự mất tích bí ẩn của các sao xung Pulsar

Sao Pulsar là những ngôi sao neutron tàn dư còn lại của những ngôi sao sao khi chết. Chúng có đặc điểm là tốc độ quay rất cao và phát ra bức xạ rất mạnh khiến chúng phát sáng như những ngọn hải đăng trong vũ trụ. Với số lượng ngôi sao đã chết rất nhiều tại trung tâm dải Ngân hà, các nhà khoa học dự tính phải có khoảng 50 Pulsar có thể quan sát được, tuy nhiên trên thực tế họ mới chỉ quan sát được một Pulsar trong dải Ngân hà.

09

Đó là một điều bí ẩn kỳ lạ, có khá nhiều giả thuyết khác nhau được đưa ra để giải thích điều này. Một trong số đó được công nhận là các sao Pulsar xoay với vận tốc rất cao này đã thu hút cả các hạt vật chất tối tại trung tâm của thiên hà. Trong khi vật chất tối là vô hình và không thể quan sát được, chúng ta chỉ có thể phát hiện qua tác động của lực hấp dẫn của vật chất tối lên những vật chất khác.

Chính vì vậy mà chúng ta không thể quan sát được các sao Pulsar này. Tuy nhiên không chỉ dừng lại ở đó, việc hút vật chất tối vào các ngôi sao Pulsar khiến cho khối lượng của chúng tăng lên gấp nhiều lần, đủ để hình thành nên một hố đen. Trong khi đó lượng vật chất tối tại trung tâm Ngân hà là rất dồi dào, có thể góp phần tạo nên nhiều hố đen mới.

10. Vũ trụ có thể được tạo ra từ một hố đen 4 chiều

Chúng ta vẫn đặt ra giả thuyết vũ trụ được hình thành từ một điểm kỳ dị với khối lượng vô cùng lớn bởi vụ nổ Big Bang, tuy nhiên các nhà khoa học chưa thể giải thích điểm kỳ dị này ở đâu ra. 3 nhà nghiên cứu tại Viện Perimeter đã đưa ra một giả thuyết mới để giải thích điều này.

10

Họ cho rằng vũ trụ của chúng ta bắt đầu từ một siêu tân tinh khổng lồ tự sụp đổ một phần tạo thành hố đen và sau đó nó hút phần vật chất còn lại để tạo thành một điểm kỳ dị có khối lượng vô cùng lớn. Tuy nhiên một hố đen thông thường là không thể hút toàn bộ vật chất ở xung quanh của nó vì chân trời sự kiện là một mặt phẳng 2D.

Do đó hố đen này phải có chân trời sự kiện 3D (3 chiều), đồng nghĩa với nó phải là một hố đen 4D. Trong khi đó vũ trụ hiện tại của chúng ta chỉ là vũ trụ 3 chiều, chúng ta vẫn chưa có kiến thức nào về chiều không gian thứ 4 này. Mặc dù vậy các nhà khoa học tỏ ra rất lạc quan với giả thuyết này, đơn giản vì nó vẫn còn bí ẩn mà có thể đến một lúc nào đó các nhà khoa học có thể lý giải.

Theo Listverse

[Dev Tip] Write a custom security token and handler in Windows Identity Foundation

In this article I will demonstrate how to write a token handler for a custom token in Windows Identity Foundation (WIF). The likely circumstances for requiring a new token type are:

  • The token type is pre-existing and needs to be federated
  • The new token type is an extension to a token type already supported by WIF

However, the purpose of this article is to demonstrate one of the extensibility points of WIF and so the reasons for creating a new token type are not so important.

Before continuing I should point out that I am not creating a new wire protocol for conveying tokens, but instead using an existing wire protocol (WS-Federation) to pass a new token type. WS-Federation is well suited to this because it is a means of conveying WS-Trust tokens using browser redirects. In turn, WS-Trust is essentially a container for …. well, any token type you like, and that is why we can create a new token type without risk of breaking any standards.

I am going to take a trial and error approach to this so that you can see some of the common pitfalls. I will simply fire a new token, wrapped within a WS-Trust 1.3 envelope and conveyed by the WS-Federation Passive Requestor Profile, as a sign-in response message to the Relying Party (RP) application. Then, I will fix the RP application by reacting to the errors that occur. Using this methodology you may get a fuller understanding of how to implement a new token handler and token.

First I need a Security Token Service (STS) to send a custom token to the RP. To do this I have captured a sign in response using Http Watch (a really good and easy to use HTTP sniffer), changed the token within the  WS-Federation wresult parameter, and hardcoded it as the STS response; this was achieved using a ASP.NET website with a HttpHandler implementation.

The custom token to be consumed by the RP looks like the following:

<m:MyCustomToken 
    xmlns:m="urn:mycustomtoken" 
    m:Id="D416881A-130B-4AFF-8091-F412D7440E39" 
    m:Issuer="urn:mycustomtokenhandlersts" 
    m:Audience="https://mycustomtokenhandlerwebsite/" 
    m:ValidFrom="2011-01-01" 
    m:ValidTo="2099-12-31">
    <m:Claim Name="GivenName" Namespace="urn:givenname">John</m:Claim>
    <m:Claim Name="Surname" Namespace="urn:surname">Doe</m:Claim>
    <m:Claim Name="Role" Namespace="urn:role">Manager</m:Claim>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
            <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
            <Reference URI="">
                <Transforms>
                    <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
                    <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                </Transforms>
                <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                <DigestValue>gK8K+94DbXsVHxE8X3ulh45WcEM=</DigestValue>
            </Reference>
        </SignedInfo>
        <SignatureValue>… removed for brevity …</SignatureValue>
        <KeyInfo>
            <X509Data>
                <X509Certificate>… removed for brevity …</X509Certificate>
            </X509Data>
        </KeyInfo>
    </Signature>
</m:MyCustomToken>

It contains many of the characteristics of common token types:

  • Id – a unique identifier for the token (can be used to detect replay attacks)
  • Namespace – the namespace for the token
  • Issuer – the entity that issued the token to the RP
  • ValidFrom/ValidTo – the validity period of the token
  • Audience – the entity that the token is intended for
  • Claims – a set of authoritative statements about the identity described by the token
  • Digital signature – ensures that the message cannot be tampered with and also enforces the authoritative nature of the message

The <microsoft.identityModel> configuration section of the RP config file currently has no awareness of the new token type:

<microsoft.identityModel>
    <service>
        <audienceUris>
            <add value="https://mycustomtokenhandlerwebsite/" />
        </audienceUris>
        <federatedAuthentication>
            <wsFederation 
                passiveRedirectEnabled="true" 
                issuer="http://localhost:29460/MyCustomTokenHandlerSTS/STSHandler.ashx" 
                realm="https://mcthw" 
                requireHttps="false" />
            <cookieHandler requireSsl="false" />
        </federatedAuthentication>
        <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry">
            <trustedIssuers />
        </issuerNameRegistry>
    </service>
</microsoft.identityModel>

OK, by browsing to the RP home page the browser is automatically redirected to the STS and the custom token is returned to the RP … Error!

“ID4014: A SecurityTokenHandler is not registered to read security token (‘MyCustomToken’, ‘urn:mycustomtoken’)”

This seems reasonable as I have not yet made any effort to recognise the token. I therefore need the bare bones of a custom SecurityTokenHandler implementation:

using System;
using Microsoft.IdentityModel.Tokens;
 
/// <summary>
/// Summary description for MyCustomTokenHandler
/// </summary>
public class MyCustomTokenHandler : SecurityTokenHandler
{
    public MyCustomTokenHandler()
    {
    }
 
    public override string[] GetTokenTypeIdentifiers()
    {
        throw new NotImplementedException();
    }
 
    public override Type TokenType
    {
        get { throw new NotImplementedException(); }
    }
}
I also need a custom System.IdentityModel.Tokens.SecurityToken implementation representing the token type to be handled:
using System;
using System.IdentityModel.Tokens;
 
/// <summary>
/// Summary description for MyCustomToken
/// </summary>
public class MyCustomToken : SecurityToken
{
    public MyCustomToken()
    {
    }
 
    public override string Id
    {
        get { throw new NotImplementedException(); }
    }
 
    public override ReadOnlyCollection<SecurityKey> SecurityKeys
    {
        get { throw new NotImplementedException(); }
    }
 
    public override DateTime ValidFrom
    {
        get { throw new NotImplementedException(); }
    }
 
    public override DateTime ValidTo
    {
        get { throw new NotImplementedException(); }
    }
}

Finally, I need to reference the handler in the RP config file by adding in a <securityTokenHandlers> element:

<securityTokenHandlers>
    <add type="MyCustomTokenHandler" />
</securityTokenHandlers>

Browse to the RP again … Error!

“The method or operation is not implemented”
This occurs because I need to implement the handlers GetTokenTypeIdentifiers method to return the namespace of the new token, and also the TokenType property to return the tokens type:
public override string[] GetTokenTypeIdentifiers()
{
    return new string[] { "urn:mycustomtoken" };
}

public override Type TokenType
{
    get { return typeof(MyCustomToken); }
}

Browse to the RP again … Error!

“ID4014: A SecurityTokenHandler is not registered to read security token (‘MyCustomToken’, ‘urn:mycustomtoken’)”
 
This is a bit strange as I have implemented all of the methods mandated by the base class. After a quick peek into the WIF source I found the following:
 
public virtual bool CanReadToken(XmlReader reader)
{
    return false;
}
 
By default all security token handler implementations are excluded as possible candidates for parsing the token! I therefore need to override this method and perform some checks on the incoming token to make sure that my code genuinely can read the token:
public override bool CanReadToken(XmlReader reader)
{
    if (reader.LocalName.Equals("MyCustomToken") &&
        reader.NamespaceURI.Equals("urn:mycustomtoken"))
    {
        return true;
    }

    return false;
}

Browse to the RP again … Error!

“ID4008: ‘SecurityTokenHandler’ does not provide an implementation for ‘ReadToken’”
 
This seems self explanatory as I have indicated that I can read the token but have provided no code to do so. I need a SecurityToken implementation but the SecurityToken base class only offers a few read-only properties. It therefore seems that I must do most of the work myself. To achieve this I have created a internal representation of the token:
using System;
using System.Collections.Generic;
using Microsoft.IdentityModel.Claims;
 
/// <summary>
/// Summary description for MyCustomTokenInternal
/// </summary>
public class MyCustomTokenInternal
{
    public string Id { get; set; }
 
    public DateTime ValidFrom { get; set; }
 
    public DateTime ValidTo { get; set; }
 
    public string Audience { get; set; }
 
    public string Issuer { get; set; }
 
    public IEnumerable<Claim> Claims { get; set; }
}
I have then used the internal token type to populate an instance of MyCustomToken in the ReadToken implementation of MyCustomTokenHandler:
public override SecurityToken ReadToken(XmlReader reader)
{
    // Check token signature using EnvelopedSignatureReader (more performant but more complex to use)
    // or SignedXml (easier to use but less performant)

    MyCustomToken token = new MyCustomToken(
        new MyCustomTokenInternal()
        {
            Id = reader.GetAttribute("Id", TokenNamespace),
            ValidFrom = XmlConvert.ToDateTime(reader.GetAttribute("ValidFrom", TokenNamespace)),
            ValidTo = XmlConvert.ToDateTime(reader.GetAttribute("ValidTo", TokenNamespace)),
            Audience = reader.GetAttribute("Audience", TokenNamespace),
            Issuer = reader.GetAttribute("Issuer", TokenNamespace),
            Claims = from el in XElement.Load(reader).Elements(XName.Get("Claim", TokenNamespace)) select new Claim(el.Attribute("Namespace").Value, el.Value)
        });

    return token;
}

Browse to the RP again … Error!

“ID4011: A SecurityTokenHandler is not registered to validate token type ‘MyCustomToken’”
Ok … as well as being able to read the token, the token handler also needs to be able to validate it. I therefore need to override the ValidateToken method and I am also going to pre-empt the possibility that I need to provide a ValidateToken implementation (as for CanReadToken/ReadToken):
public override bool CanValidateToken
{
    get
    {
        return true;
    }
}
 
public override ClaimsIdentityCollection ValidateToken(SecurityToken token)
{
    ClaimsIdentityCollection idColl = new ClaimsIdentityCollection();
    IClaimsIdentity id = new ClaimsIdentity((token as MyCustomToken).Claims);
    idColl.Add(id);
    return idColl;
}
Browse to the RP again … Success!
image_2_2F5D7C2C[1]
Finally, to prove that the token conditions are being honoured by WIF I have changed the ValidTo date to a time in the past. When I now attempt to browse to the RP I get the following error:
“Specified argument was out of the range of valid values. Parameter name: validFrom”
Which is slightly odd as it is the ValidTo date that is incorrect, but at least an error occurs.
In conclusion, I have shown how it is possible to consume a custom token type in WIF using the SecurityToken and SecurityTokenHandler classes.
Finally I have included the complete classes below for reference.
Have fun!
Written by Bradley Cotier
MyCustomTokenHandler:
using System;
using System.IdentityModel.Tokens;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using Microsoft.IdentityModel.Claims;
using Microsoft.IdentityModel.Tokens;

/// <summary>
/// Summary description for MyCustomTokenHandler
/// </summary>
public class MyCustomTokenHandler : SecurityTokenHandler
{
    private const string TokenNamespace = "urn:mycustomtoken";

    public MyCustomTokenHandler()
    {
    }

    public override string[] GetTokenTypeIdentifiers()
    {
        return new string[] { TokenNamespace };
    }

    public override Type TokenType
    {
        get { return typeof(MyCustomToken); }
    }

    public override bool CanReadKeyIdentifierClause(XmlReader reader)
    {
        if (reader.LocalName.Equals("X509Data"))
        {
            return true;
        }

        return false;
    }

    public override bool CanReadToken(XmlReader reader)
    {
        if (reader.LocalName.Equals("MyCustomToken") &&
            reader.NamespaceURI.Equals("urn:mycustomtoken"))
        {
            return true;
        }

        return false;
    }

    public override SecurityToken ReadToken(XmlReader reader)
    {
        // Check token signature using EnvelopedSignatureReader (more performant but more complex to use)
        // or SignedXml (easier to use but less performant)

        MyCustomToken token = new MyCustomToken(
            new MyCustomTokenInternal()
            {
                Id = reader.GetAttribute("Id", TokenNamespace),
                ValidFrom = XmlConvert.ToDateTime(reader.GetAttribute("ValidFrom", TokenNamespace)),
                ValidTo = XmlConvert.ToDateTime(reader.GetAttribute("ValidTo", TokenNamespace)),
                Audience = reader.GetAttribute("Audience", TokenNamespace),
                Issuer = reader.GetAttribute("Issuer", TokenNamespace),
                Claims = from el in XElement.Load(reader).Elements(XName.Get("Claim", TokenNamespace)) select new Claim(el.Attribute("Namespace").Value, el.Value)
            });

        return token;
    }

    public override bool CanValidateToken
    {
        get
        {
            return true;
        }
    }

    public override ClaimsIdentityCollection ValidateToken(SecurityToken token)
    {
        ClaimsIdentityCollection idColl = new ClaimsIdentityCollection();

        IClaimsIdentity id = new ClaimsIdentity((token as MyCustomToken).Claims);

        idColl.Add(id);

        return idColl;
    }
}
MyCustomToken:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IdentityModel.Tokens;
using Microsoft.IdentityModel.Claims;

/// <summary>
/// Summary description for MyCustomToken
/// </summary>
public class MyCustomToken : SecurityToken
{
    private MyCustomTokenInternal tokenInt;

    public MyCustomToken(MyCustomTokenInternal tokenInt)
    {
        this.tokenInt = tokenInt;
    }

    public override string Id
    {
        get { return this.tokenInt.Id; }
    }

    public override ReadOnlyCollection<SecurityKey> SecurityKeys
    {
        get { return null; }
    }

    public override DateTime ValidFrom
    {
        get { return this.tokenInt.ValidFrom; }
    }

    public override DateTime ValidTo
    {
        get { return this.tokenInt.ValidTo; }
    }

    public IEnumerable<Claim> Claims
    {
        get { return this.tokenInt.Claims; }
    }
}
MyCustomTokenInternal:
using System;
using System.Collections.Generic;
using Microsoft.IdentityModel.Claims;
 
/// <summary>
/// Summary description for MyCustomTokenInternal
/// </summary>
public class MyCustomTokenInternal
{
    public string Id { get; set; }
 
    public DateTime ValidFrom { get; set; }
 
    public DateTime ValidTo { get; set; }
 
    public string Audience { get; set; }
 
    public string Issuer { get; set; }
 
    public IEnumerable<Claim> Claims { get; set; }
}
RP web.config <microsoft.identityModel> config section:
<microsoft.identityModel>
    <service>
        <audienceUris>
            <add value="https://mycustomtokenhandlerwebsite/" />
        </audienceUris>
        <federatedAuthentication>
            <wsFederation 
                passiveRedirectEnabled="true" 
                issuer="http://localhost:29460/MyCustomTokenHandlerSTS/STSHandler.ashx" 
                realm="http://localhost:58724/MyCustomTokenHandlerWebsite/" 
                requireHttps="false" />
            <cookieHandler requireSsl="false" />
        </federatedAuthentication>
        <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry">
            <trustedIssuers />
        </issuerNameRegistry>
        <securityTokenHandlers>
            <add type="MyCustomTokenHandler" />
        </securityTokenHandlers>
    </service>
</microsoft.identityModel>

REF: 
http://blogs.msdn.com/b/mcsuksoldev/archive/2011/03/25/write-a-custom-security-token-and-handler-in-windows-identity-foundation.aspx
https://github.com/IdentityServer/Thinktecture.IdentityServer3

[Dev Tip] Single Sign On (SSO) for cross-domain ASP.NET applications

Introduction

“Yet another Monday morning at your office. Just started to wonder how fast the weekend just passed away, and how hard are the days going to be in this week. You got a mail! Oh no, not a lucrative job offer. It’s just another requirement from your new client. Your client has a number of ASP.NET of sites, and all he wants is to enable his users to log onto all sites just by logging into a single site. And, obviously, log out of all sites by logging out from a single site.

OK, so your client wants a “Single Sign On” implementation. You thought, oh, it’s not that hard. The ASP.NET forms authentication is the solution. It allows to share the same cookie across sites under the same domain using the same configuration key using the <machineKey> element. A quick Google search gives you some pretty fine examples of Single Sign On implementation using <machineKey> in ASP.NET applications. OK, so life is not that hard as a programmer after all.

Hold on. Something just caught your eyes. The requirement says, “your client has a number of sites, but they are not necessarily under the same domain“. You just missed this important point, and, the very first day at your office just started to appear harder to you. It’s not easy to implement a Single Sign On for sites under different domains, for the very fundamental reason that, the cookie of a particular domain cannot be shared with another domain. Who doesn’t know that it’s the cookie that is used to maintain authentication information across different page requests?”

I just depicted a scenario that is pretty common these days. This is an era of web 2.0 and social networking, as they say. Standalone and “island” like systems are very rare these days. You do a tweet from Twitter and update your status at LinkedIn and Facebook at the same time without doing anything else. You write an article on CodeProject and share it on hundreds of sites within seconds. So, it’s pretty natural that you would expect to log onto a site and jump to another related one without having to re-login again, doesn’t matter to you what domain these sites are deployed under.

So I thought, how about developing something that allows to easily implement a Single Sign On (of course, for ASP.NET sites) for cross-domain sites? People may have tried to implement this in many different ways, and commercial solutions are also available upon purchase. But, what if I try to develop something which is simple, free, and most importantly, works.

How authentication works in ASP.NET

Well, this may not be something new to you. But while we try to solve the hardest problems on earth, we often need to go back to the basics, to try to understand how things really work. So, it wouldn’t be bad to revisit the ABS’s of the ASP.NET forms authentication mechanism.

Here is how ASP.NET forms authentication works:

Forms_Authentication.png

Forms authentication in ASP.NET

Sequence of operations:

  • You hit a page in an ASP.NET application which is accessible only to the authenticated users (logged in users) of the application.
  • The ASP.NET runtime looks for a cookie (forms authentication cookie) in the request, and if the cookie is not found, it redirects the current request to the login page (the login page location is configured in theweb.config).
  • You provide the login credentials and hit the “Login” button. Assuming that the credentials are correct, your system validates the credentials successfully against the data storage, sets the user name to theThread.CurrentPrincipal.Identity.Name property, writes a cookie in the Response (along with setting the cookie value with the user information and setting some properties like cookie name, expiration date/time etc.), and redirects to the originally requested page.
  • You hit another page in the application (or, click a link that navigates you to another page), and your browser sends the authentication cookie (with any other cookie that were written by the same site earlier), this time because the browser has already got the authentication cookie in the last response.
  • As usual, the ASP.NET runtime looks for the authentication cookie in the request, and this time it finds the cookie. It checks the cookie properties (like expiration date/time, path etc.), and if not expired already, reads the cookie value, retrieves the user information from the cookie, sets the user name into theThread.CurrentPrincipal.Identity.Name property, checks if the user has permission to access the requested page, and if he/she has permission, executes and serves the page to the browser.

Pretty simple, right?

How authentication works in multiple ASP.NET sites under the same domain

As depicted already, the ASP.NET forms authentication is fully dependent on Cookies. So, if two different sites can share the same authentication cookie, it is possible to make the same user to log onto both sites just by logging onto a single site.

Now, the HTTP protocol says, two different sites can share a cookie if and only if both sites are deployed under the same domain (or, sub-domain). Internally, your browser stores the cookies locally (either in disk or in memory) against the web site’s URL. When you hit subsequent requests to any site, the browser reads those cookies which have matching domain or sub domain names comparing to the currently requested URL and sends those cookies with the request.

So, let’s assume you have two sites as follows:

These two sites share the same host address (same domain mydomain.dom and sub-domain www), and both sites have been configured to use forms authentication for user authentication and authorization. Suppose you just logged onto the http://www.mydomain.com/site1 site, and as described above, your browser now has a forms authentication cookie originated from http://www.mydomain.com/site1.

Now, if you click/hit any subsequent URL of http://www.mydomain.com/site1, the forms authentication cookie will be sent with the request. Why? Because the cookie originally belongs to this site? Yes, but not 100% correct. To be exact, the cookie will be sent because the request URL http://www.mydomain.com/site1 has the same matching sub domain and domain name (host address) http://www.mydomain.com.

So, after you logged onto http://www.mydomain.com/site1, if you hit a URL of http://www.mydomain.com/site2, the forms authentication cookie (or, any other matching cookie) will be sent with the request for the very same reason thathttp://www.mydomain.com/site2 has the same matching host address (http://www.mydomain.com) even if this is a different application (site2). So, it’s obvious that as the same forms authentication cookie can be shared across two different web applications under the same host address, it’s possible to log onto both web applications at the same time just by logging onto a single web application (hence, Single Sign On).

However, ASP.NET does not allow you to automatically implement Single Sign On just by implementing forms authentication for multiple web applications under the same host address. Why? Because, each different ASP.NET web application uses its own encryption keys to encrypt and decrypt cookie data (and other data such as ViewState) for ensuring security. So, unless you specify a single encryption key for each ASP.NET application, cookies will be sent from the browser, but an application won’t be able to read the value of an authentication cookie that is originated from another application.

Specifying a single authentication key is the solution. For each ASP.NET application, you have to use the same<machinekey> element in the web.config, as follows:

<machineKey 
  validationKey="21F090935F6E49C2C797F69BBAAD8402ABD2EE0B667A8B44EA7DD4374267A75D" 
  decryptionKey="ABAA84D7EC4BB56D75D217CECFFB9628809BDB8BF91CFCD64568A145BE59719F"
  validation="SHA1"
  decryption="AES"/>

If the same machinekey (with validationKey and decryptionKey) is used across all applications under the same domain, each will be able to read cookie values that originate from other applications.

What if two sites have the same domain and different sub domains?

Suppose your sites are deployed under the following host addresses:

  • site1.mydomain.com
  • site2.mydomain.com

These two sites share the same domain (same second level domain mydomain.com), but has differ in their third level domain (different sub domains site1 and site2).

By default, the browser sends cookies for matching host addresses only (matching domain and sub domain). So, the site site1.mydomain.com won’t get any cookie that is originated form site2.mydomain.com (because they don’t have the same host address, their sub domain is different), and hence even if you configure the samemachineKey for these two sites, one site won’t be able to get cookies originated from another.

So, in addition to implementing the same machineKey across all sites, you also need to instruct the ASP.NET runtime to define the domain of an authentication cookie so that the cookie is sent from the browser with any request that has a matching domain name. You need to configure the forms authentication cookie as follows:

<forms name="name" loginUrl="URL" defaultUrl="URL" domain="mydomain.com"/>

So, how to share the authentication cookie across multiple domains?

Well, there is absolutely no way to do that. The fundamental barrier of the HTTP protocol prevents you from sharing a cookie across different domains, primarily for security reasons.

Say, you have the following two sites under two different domains:

Now, if you log onto the http://www.domain1.com site using forms authentication, and hit a URL of http://www.domain2.com, the browser wouldn’t simply send the authentication cookie of domain1.com to domain2.com. There is no built-in mechanism in ASP.NET to implement a Single Sign On across these two different sites.

In order to implement a Single Sign On across these two sites under different domains, there has to be some “workaround” or some implementation model that lets these two sites to access a single cookie via some “indirect” mechanism.

A very basic Cross Domain SSO implementation model

Suppose we have to implement SSO in these sites:

In order to implement SSO across these sites, we need to set an authentication cookie to the client’s browser for all three sites when the user is authenticated in any one of the two sites.

If user1 is authenticated into http://www.domain1.com, the browser will add an authentication cookie in the response before returning a response to http://www.domain1.com. But as we need to be able to log onto http://www.domain2.com andhttp://www.domain3.com, we need to set the authentication cookie in the same client’s browser for http://www.domain2.comand http://www.domain3.com at the same time. So, before returning the response to the browser, http://www.domain1.comwill have to redirect the browser to http://www.domain2.com and http://www.domain3.com for setting the authentication cookie.

The following diagram depicts the basic idea (arrows denote the redirections):

Basic_SSO_model_overview.png

Basic SSO model overview

And the following sequence diagram depicts the detailed idea:

SSO_Basic_Model.png

Sequence diagram of login operation in the basic SSO model

Sequence of operations:

[Status:  browser has no authentication cookie]
[Status:  browser has no authentication cookie]
[Status:  browser has no authentication cookie]
    • User provides login credentials and hits the “Login” button. Browser sends a POST request tohttp://www.domain1.com.
[Status:  browser has no authentication cookie]
    • http://www.domain1.com accepts the login credentials, verifies the credentials against a data storage, and upon success, marks the user as logged in, creates an authentication cookie with the logged in user’s information, and adds to the response.
[Status : browser has no authentication cookie]
[Status : browser has no authentication cookie]
[Status : browser has an authentication cookie for www.domain2.com]
    • http://www.domain2.com immediately redirects to the ReturnUrl address with setting an authentication cookie for http://www.domain1.com by reading the cookie value from the request. Eventually, the authentication cookie is also sent with the response with the redirect command.
[Status : browser has an authentication cookie for www.domain2.com]
[Status : browser has authentication cookie 
          for both www.domain1.com and www.domain2.com].
    • http://www.domain1.com sees that the authentication cookie is already set in the request, and hence instead of returning the login page, it serves the page that is requested.
[Status : browser has authentication cookie 
          for both www.domain1.com and www.domain2.com].

So, if the user hits an authenticated page of http://www.domain2.com in the browser now, as the authentication cookie is already stored in the browser for http://www.domain2.com, it is sent with the request, and http://www.domain2.comretrieves the user information from the authentication cookie, logs in the user, and serves the page output that is requested by the user.

As the browser now has authentication cookie for both http://www.domain2.com and http://www.domain3.com, the user is considered to be logged onto both sites, and hence, Single Sign On implemented in both sites Smile | :)

How about “Single Sign Out”?

If we only had to manage logging onto the sites for users, we would have been done so far. But as part of the Single Sign On, we also have to manage the “Single Sign Out“. That is, when a user signs out of a single site, the user should be marked as signed out of all the sites.

Internally, when the user signs out of a single site (say, http://www.domain1.com), the authentication cookie of all the other sites needs to be removed from the browser (in this case, http://www.domain2.com). A cookie can be removed from the browser by removing the cookie from the response before sending the response to the browser.

To remove all authentication cookies for all sites, the same flow of request-redirect-response described above should be followed, and instead of setting the authentication cookie, this time, the authentication cookie should be removed from the response.

Problem with this SSO model

This model should work fine for two sites. For logging into a site and for logging out of a site, the corresponding site internally should follow a request-redirect-response flow with all other sites (that are under the SSO). Once the user is logged onto a single site, for all other subsequent requests onto any site, there is no request-redirect-response loop because each site has its own authentication cookie stored in the browser.

But, if the number of sites is more than 2, the complexity increases. That is, if the user logs ontohttp://www.domain1.com, this site will internally redirect to http://www.domain2.com and http://www.domain3.com for setting the authentication cookie in the browser, and finally http://www.domain3.com redirects to http://www.domain1.com and serves the originally requested page output to the browser. This will make the login and logout functionality of each site costly and complex. What if there are more than 3 sites? What if we have 20+ sites to integrate under a Single Sign On model which are deployed under different domains? The model is obviously not going to fit.

This model also requires each site to have knowledge about all the other sites which are configured under the same SSO umbrella (because, each site has to redirect to all the other sites for setting the authentication cookie). Also, this would require the user authentication and authorization logic to be implemented on each site.

It’s clearly understandable, as the number of sites increases, this SSO model will become messy, and will lose its acceptance, and this model can’t really be considered a “generic” SSO model for cross-domain applications. So, we need a better model that should be independent of the number of sites to integrate under a Single Sign On umbrella.

A proposed model for Cross-Domain SSO

The previous model was kind of a “mesh-up” where each site had to be redirected to N-1 other sites for setting and removing authentication cookie for signing in and signing out. Each site had to be configured with knowledge of the other N-1 sites, and some complex and expensive login and logout logic had to be implemented.

What if we maintained a single authentication cookie for tracking user authentication for all sites? What about introducing a new dedicated site for authenticating users and setting the authentication cookie? Sounds lucrative.

In order to implement SSO for multiple sites, the user database should be a unified one, and hence, it makes good sense to implement the user authentication and authorization functionality within a dedicated site where each site can access the functionality via a web or WCF service. This allows the sites to get rid of redundant user authentication/authorization functionality. But the most important question is how this dedicated site is going to help implement Single Sign On.

Well, in this model, the browser will not store authentication cookies for each site. Rather, it will store an authentication cookie for only the dedicated site which will be used by the other sites to implement Single Sign On. Let’s call this site http://www.sso.com.

In this model, each and every request to any site (which takes part in the SSO model) will internally be redirected to the SSO site (http://www.sso.com) for setting and checking the existence of an authentication cookie. If the cookie is found, the authenticated pages are served to the browser, and if not, the user is redirected to the login page of the corresponding site.

The following diagram depicts the basic idea:

Proposed_SSO_model_overview.png

A dedicated site (www.sso.com) for managing the authentication cookie in the proposed SSO model

For understanding the model in detail, let’s imagine we are trying to apply this model to implement SSO to the following two sites:

We now have a dedicated site for managing the authentication cookie: http://www.sso.com.

Here is how this model works:

SSO_Proposed_Model_Part_I.png

Sequence diagram of an authenticated page hit without login

Sequence of operations:

SSO_Proposed_Model_Part_II.png

Sequence diagram of login
    • User provides credentials and hits the “Login” button. No postback request is redirected to the SSO site in this model. This time, http://www.domain1.com invokes the web/WCF service of http://www.sso.com to check the provided user credentials, and upon success, returns the user object with a Token property that is generated each time a user logs in (say, a GUID).
    • http://www.domain1.com marks the user as logged in (say, stores the user object in the session), prepares a URL with the user Token, and redirects the current request to http://www.sso.com to set the authentication cookie, with the ReturnUrl parameter value being set to the original request URL.
    • http://www.sso.com checks the incoming request URL, and finds a user Token, with no authentication cookie being available yet. That indicates the user has been authenticated into the client site (http://www.domain1.com), and the authentication cookie now needs to be set in the browser for http://www.sso.com. So, it retrieves the user from the cache using the Token, prepares an authentication cookie with the user info and sets the other cookie properties (expiration date/time etc.), adds the cookie to the response, and finally redirects to the originally requested URL found in the ReturnUrl query string value (a URL of http://www.domain1.com), along with adding the Token value in the query string.
    • Browser gets a Redirect command now with ReturnUrl to http://www.domain1.com, and also gets an authentication cookie from http://www.sso.com. So it stores the authentication cookie for http://www.sso.com and hits a request to the URL at http://www.domain1.com.
    • http://www.domain1.com now sees that a user Token is present in the query string. It validates the user token via a web/WCF service call at http://www.sso.com, and upon validation, executes the originally requested page ofhttp://www.domain1.com and writes the output in the response.

SSO_Proposed_Model_Part_III.png

Sequence diagram of browsing an authenticated page after login
  • User hits an authenticated page URL of http://www.domain2.com now.
  • http://www.domain2.com redirects the request to http://www.sso.com in the client’s browser, setting the ReturnUrlproperty to the originally requested URL of http://www.domain2.com.
  • The browser gets a redirect command to http://www.sso.com. It already has an authentication cookie stored for this site, and hence adds this cookie to the request before sending the request to http://www.sso.com.
  • http://www.sso.com checks the incoming request and looks for any authentication cookie in the request. If finds an authentication cookie this time, and checks whether the cookie has expired. If not, it retrieves the userToken from the cookie and redirects the request to the originally requested page URL athttp://www.domain2.com, setting the user Token in the query string.
  • http://www.domain2.com sees that there is a user Token presented in the query string. So it validates the user token via a web/WCF service call at http://www.sso.com, and upon validation, executes the originally requested page of http://www.domain2.com and writes the output in the response.

To summarize

Wow, sounds a lot of things are happening! Let me summarize those here:

Initially, the browser doesn’t have any authentication cookie for http://www.sso.com. So, hitting any authenticated page in the browser for http://www.domain1.com or http://www.domain2.com redirects the user to the login page (via an internal redirection to http://www.sso.com for checking the existence of the authentication cookie). Once a user is logged onto a site, the authentication cookie for http://www.sso.com is set in the browser with the logged in user information (most importantly, the user Token, which is valid only for the user’s login session).

Now, if the user hits any authenticated page URL of http://www.domain1.com or http://www.domain2.com, the request is internally redirected to http://www.sso.com in the user’s browser, and the browser sends the authentication cookie, which is already set. http://www.sso.com finds the authentication cookie, extracts the user Token, and redirects to the originally requested URL in the browser with the user token, and the originally requested site validates the Tokenand serves the page that was originally requested by the user.

Once the user is logged onto any site under this SSO model, hitting any authenticated page onhttp://www.domain1.com or http://www.domain2.com results in an internal redirection to http://www.sso.com (for checking the authentication cookie and retrieving the user Token) and then serving the authentication page in the browser output.

Traffic

Following are the summary of traffic for each different scenario:

Scenario1: A public page hit

A trip from the browser to the client site + a trip from the client site to the browser

Summary: 1 Request + 1 Response

Scenario2: An authenticated page hit without login

A trip from the browser to the client site (page hit) + a redirect command to the browser and a trip from the browser to the SSO site (redirect to SSO for cookie check) + a redirect command to the browser and a trip from the browser to the client site (redirect to client site without cookie) + a trip from the client site to the browser (login page)

Summary: 1 Request + 2 Redirects + 1 Response

Scenario3: Login

A trip from the browser to the client site (postback) + an invocation of the authentication Web Service (user authentication) + a redirect command to the browser and and a trip from the browser to the SSO site (redirect to SSO with Token) + a redirect command to the browser and a trip from the browser to the client site (setting the authentication cookie) + an invocation of a Web Service method (Token validation) + a trip from the client site to the browser (serve the authenticated page)

Summary: 1 Request + 2 Web Service calls at the server + 2 Redirects + 1 Response

Scenario4: Browse an authenticated page while logged in

A trip from the browser to the client site (URL hit) + a redirect command to the browser and a trip from the browser to the SSO site (redirect to SSO with the authentication cookie) + a redirect command to the browser and a trip from the browser to the client site (checking the authentication cookie) + an invocation of a Web Service method (Token validation) + a trip from the client site to the browser (serve the page)

Summary: 1 Request + 2 Redirect + 1 Web Service call at the server + 1 Response

Scenario5: Logout

A trip from the browser to the client site (click logout link) + a redirect command to the browser and a trip from the browser to the SSO site (instruction to log out) + a redirect command to the browser and a trip from the browser to the client site (after removing the authentication cookie) + a trip from the client site to the browser (serve the login page)

Summary: 1 Request + 2 Redirects + 1 Response

Trade offs

Comparing the basic SSO model and the proposed one, it seems the basic model suits well for 2, or, at most 3 sites. In the case of the basic SSO model, the login and logout functionality will be complex in terms of implementation and execution time, but the subsequent pages would be served in a normal request-response cycle (1 request and 1 response).

However, extending the SSO is difficult (addition of new sites), configuration management is maximum (each site has to manage their own cookie and each has dependency on other sites), and redundant user authentication functionality has to be implemented on multiple sites.

On the other hand, the proposed model does not have any dependency on the number of sites to integrate (you can add as many sites as you want and the SSO model won’t change). The configuration management is minimum for the participating site (no site has to know about the other sites, they need only know about the SSO site), the authentication and cookie management is handed over to a dedicated site (http://www.sso.com), the SSO related functionality can be easily integrated with the site if implemented smartly, and could be extended easily (new sites could be added easily).

However, there is a small performance penalty. Unlike the basic model, each authenticated page access requires3 requests from the browser to the SSO site and the client site (the two additional requests are due to the two internal redirects). Though, the additional two requests take minimum execution time (a blank redirect request, just for setting and checking the cookie), and hence could be considered acceptable considering today’s high Internet bandwidth availablilty.

Implementation of the proposed SSO model

Enough theories, and we should be prepared well enough now to get our hands dirty with some code. Good that I already have done it and have shared it in the next article. The following article would present an actual implementation of the proposed SSO model for Cross-Domain ASP.NET sites, and would point out some implementation challenges and their workarounds:

The implementation

Yes, I have done a sample SSO application based on the proposed model. It’s not just another “Hello world”, it’s a working application that implements SSO across three different sites under three different domains. The hard work is done, and the soft output is, you just need to extend a class for making an ASPX page a “Single Sign On” enabled one in your ASP.NET application. You, of course, have to set up an SSO site and configure your client applications to use the SSO site, that’s all (merely a 10 minute work).

The SSO implementation is based on the following high level architecture:

CrossDomainSSOExample/Proposed_SSO_model_overview.png

Figure : The Single Sign On implementation model

There may be unlimited number of client sites (in our example, 3 sites) which could participate under a “Single Sign On” umbrella, with the help of a single “Single Sign On” server (call this the SSO site, http://www.sso.com). As described in the previous article, the browser will not store an authentication cookie for each different client site in this model. Rather, it will store an authentication cookie for only the SSO site (http://www.sso.com) which will be used by the other sites to implement Single Sign On.

In this model, each and every request to any client site (which takes part in the SSO model) will internally be redirected to the SSO site (http://www.sso.com) for setting and checking the existence of the authentication cookie. If the cookie is found, the authenticated pages for the client sites (that are currently requested by the browser) are served to the browser, and if not found, the user is redirected to the login page of the corresponding site.

How it works

Initially, the browser doesn’t have any authentication cookie stored for http://www.sso.com. So, hitting any authenticated page in the browser for http://www.domain1.com, or http://www.domain2.com, or http://www.domain3.com redirects the user to the login page (via an internal redirection to http://www.sso.com for checking the existence of the authentication cookie). Once a user is logged onto a site, the authentication cookie for http://www.sso.com is set in the browser with the logged in user information (most importantly, the user Token, which is valid only for the user’s login session).

Now, if the user hits any authenticated page URL of http://www.domain1.com, or http://www.domain2.com orhttp://www.domain3.com, the request is internally redirected to http://www.sso.com in the user’s browser and the browser sends the authentication cookie, which is already set. http://www.sso.com finds the authentication cookie, extracts the user Token, and redirects to the originally requested URL in the browser with the user token, and the originally requested site validates the Token and serves the page that was originally requested by the user.

Once the user is logged onto any site under this SSO model, hitting any authenticated page onhttp://www.domain1.com, or http://www.domain2.com, or http://www.domain3.com results in an internal redirection to http://www.sso.com(for checking the authentication cookie and retrieving the user Token) and then serving the authentication page in the browser output.

OK, show me what you implemented

I have developed a sample Single Sign On application that incorporates three different sites (http://www.domain1.com,http://www.domain2.com, and http://www.domain3.com) and an SSO server site (http://www.sso.com). The sample SSO implementation code is available for download with this article. You just need to download and set up the sites as instructed in the next section. Once you are done with that, you can test the implementation in different scenarios.

The following section has step by step instructions to test the Single Sign On functionality in different scenarios, and each testing scenario has a Firebug network traffic information that depicts the total number of requests (including the lightweight redirect requests) and their length in size. The number of redirect requests and their length in size are marked within green for easy understandability.

Scenario1: Before authentication

Hit the following three URLs in the browser in three different tabs of the same browser window.

CrossDomainSSOExample/LoginUrlSSO.png

Three different login screens will be presented in each different tabs, for each different site:

CrossDomainSSOExample/Login1.png

CrossDomainSSOExample/Login2.png

CrossDomainSSOExample/Login3.png

Traffic info

For presenting the login screen, in total, four requests are sent to the servers, among which three are redirect requests (marked in green). The redirect request sizes are very small (in terms of bytes), and are negligible even considering network latency.

CrossDomainSSOExample/TrafficLogin.png

Scenario 2: Authentication

Use one of any following credentials in any one of the login screens to log on. Let’s log onto http://www.domain1.comwith user1/123.

Available credentials:

  • user1/123
  • user2/123
  • user3/123

After login, the following screen will be provided for user1 onto http://www.domain1.com.

CrossDomainSSOExample/Home1.png

Traffic info

For login, in total, three requests are sent to the servers, among which two are redirect requests (marked in green). The redirect request sizes are very small (in terms of bytes), and are negligible even considering network latency.

CrossDomainSSOExample/TrafficAuthentication.png

Scenario 3: After authentication

As user1 has logged on to http://www.domain1.com, he should be logged onto the other remaining sites:http://www.domain2.com and http://www.domain3.com at the same time, if those sites are browsed in the same window or in different tabs in the same window. Hitting an authenticated page in http://www.domain2.com and http://www.domain3.comshould not present a login screen.

Let’s just refresh the current page at http://www.domain2.com and http://www.domain3.com in their corresponding window (currently, the login screen is being shown in the browser):

CrossDomainSSOExample/Home2.png

CrossDomainSSOExample/Home3.png

You will see that instead of showing the login screen, the authenticated home page is being shown. So, user1 is logged onto all three sites: http://www.domain2.com, http://www.domain2.com, and http://www.domain3.com.

Each home page shows a “Go to Profile Page” link which you can click to navigate to another page. This demonstrates that clicking on hyperlinks and navigating to other pages in the application also works without any problem.

Traffic info

For browsing authenticated pages after login, in total, 3 requests are sent to the servers, among which 2 are redirect requests (marked in green). The redirect request sizes are also very small (in terms of bytes), and are negligible even considering network latency.

CrossDomainSSOExample/TrafficAuthentication.png

Scenario 4: Hit the authenticated page on a different session

As expected, the user’s “Sign on” status should only be valid for the current session ID, and any authenticated page URL hit to any one of the three sites will be successful if the URL is hit in the same browser window or in a different tab of the same browser window. But, if a new browser window is opened, and an authenticated URL is hit there, it should not be successful and the request should be redirected to the login page (because that is a different browser session).

To test this, open a new browser window and hit any URL of the three sites that points to an authenticated page (you can copy and paste the existing URL addresses). This time, instead of showing the page output, you will see the request will be redirected to the login page as follows (assuming that you hit a URL of http://www.domain3.com):

CrossDomainSSOExample/Login3.png

Traffic info

For hitting an authenticated page on a different session, in total, 4 requests are sent to the servers, among which 3 are redirect requests (marked in green). The redirect request sizes are very small (in terms of bytes), and are negligible even considering network latency.

CrossDomainSSOExample/TrafficLogin.png

Log out

To log out of the sites, click on the “Log out” link of the home page of http://www.domain1.com. The system will log outuser1 from the site http://www.domain1.com and will redirect to the login screen again:

CrossDomainSSOExample/Login1.png

Traffic info

For logging out, in total, 4 requests are sent to the servers, among which 3 are redirect requests (marked in green). The redirect request sizes are very small (in terms of bytes), and are negligible even considering network latency.

CrossDomainSSOExample/TrafficLogout.png

After log out

As user1 is logged out of the site http://www.domain1.com, he should be logged out from http://www.domain2.com andhttp://www.domain3.com at the same time. So, hitting any authenticated page URL of http://www.domain2.com andhttp://www.domain3.com should now redirect to their corresponding login screens.

To test this, refresh the current page of http://www.domain2.com and http://www.domain3.com. Instead of refreshing the page, the system will now redirect the requests to their login pages:

CrossDomainSSOExample/Login2.png

CrossDomainSSOExample/Login3.png

Traffic info

Same as login.

Great… this seems to be working! How do I set up the sites?

The sample SSO implementation has been developed using Visual Studio 2010, .NET 4.0 Framework, and tested in IIS 7 under a Windows Vista machine. However, it doesn’t use any 4.0 framework specific technology or class library and hence, it can be converted to use for a lower level framework without much effort, if required.

Follow these steps to set up the example SSO implementation in your machine:

    • Download SSO.zip and extract to any convenient location in your PC. The following folders/files will be extracted within the folder “SSO“:

    • Click on “SSO.sln” to open the solution in Visual Studio, to understand “Who is What” in the solution structure:

CrossDomainSSOExample/SolutionExplorer.png

As the names imply:

      • C:\…\www.domain1.com is the website for http://www.domain1.com
      • C:\…\www.domain2.com is the website for http://www.domain2.com
      • C:\…\www.domain3.com is the website for http://www.domain3.com
      • C:\…\www.sso.com is the web site for http://www.sso.com
      • SSOLib is a Class Library that handles all the Single Sign On related logic along with communicating with the SSO site via a Web Service, on behalf of the client sites.
    • Type “inetmgr” in the Run command to launch the IIS Manager (alternatively, you can navigate to the IIS Manager from Start->Program files) and create a site there named “http://www.domain1.com“:

Right click on “Sites” and click on “Add Web Site…“:

CrossDomainSSOExample/AddNewSite.png

Provide the necessary inputs in the following input form and click “OK”:

CrossDomainSSOExample/CreateSiteDomain1.png

The site “http://www.domain1.com” will be created in IIS. After creating the site, the site might be shown with a red cross sign in IIS Explorer, indicating that the site is not started yet (this happens in my IIS in Windows Vista Home Premium). In this case, you need to select the site and click on the Restart icon to make sure it starts (the Restart icon is available in the right-middle portion of the screen in IIS Explorer).

CrossDomainSSOExample/RestartSite.png

CrossDomainSSOExample/CreateAllSites.png

    • Click on the “Application Pool” node in IIS Explorer. The application pool listing will be shown in the right pane, and you will see the application pools for the corresponding sites that you’ve just created in IIS.

Make sure all application pools are running under .NET Framework 4.0 (as the web application has been built in Framework 4.0). To do that, right click on the corresponding application pools (that have the same names as the site names) and select the .NET Framework version in the form:

CrossDomainSSOExample/ApplicationPool.png

    • Edit the Hosts file (C:\Windows\System32\drivers\etc\hosts) so that the site names are mapped to the localhost loopback address (127.0.0.1):
127.0.0.1       localhost
127.0.0.1       www.domain1.com
127.0.0.1       www.domain2.com
127.0.0.1       www.domain3.com
127.0.0.1       www.sso.com

If things are correctly done, you should be able to run the sites and test correctly as shown above. Otherwise, please verify if there is any thing missing or misconfigured by reviewing the steps from the start.

OK, how do I implement SSO for my sites?

Good question. The sample SSO implementation works fine. But, as a developer, you would likely be more interested in how to implement SSO in your ASP.NET sites using the things developed. While implementing the SSO model, I tried to make a pluggable component (SSOLib.dll) so that it requires minimum programmatic change and configuration. Assuming that you have some existing ASP.NET applications, you need the following steps to implement “Single Sign On” across them:

    • Add a reference to “SSOLib.dll“, or add a reference to the “SSOLib” project to each ASP.NET application.
    • Set up the SSO site (see previous steps).
    • Configure your ASP.NET applications to use the SSO site. To do this, just add the following configurations in the web.confing of each ASP.NET application:
<!--Configuration section for SSOLib-->
 <configSections>
    <sectionGroup name="applicationSettings" 
         type="System.Configuration.ApplicationSettingsGroup, System, 
               Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <section name="SSOLib.Properties.Settings" 
        type="System.Configuration.ClientSettingsSection, System, 
              Version=4.0.0.0, Culture=neutral, 
              PublicKeyToken=b77a5c561934e089" 
        requirePermission="false" />
    </sectionGroup>
 </configSections>
 <applicationSettings>
    <SSOLib.Properties.Settings>
     <setting name="SSOLib_Service_AuthService" serializeAs="String">
       <value>http://www.sso.com/AuthService.asmx</value>
     </setting>
    </SSOLib.Properties.Settings>
 </applicationSettings>
 <appSettings>
       <add key="SSO_SITE_URL" 
         value="http://www.sso.com/Authenticate.aspx?ReturnUrl={0}" />
       <add key="LOGIN_URL" value="~/Login.aspx" />
       <add key="DEFAULT_URL" value="~/Page.aspx" />
   </appSettings>
<!--End Configuration section for SSOLib-->

Note: Modify the configuration values according to the SSO site URL of your setup and your application specific needs.

  • Modify the code-behind classes (*.aspx.cs) of the login page and other private pages (pages which are accessible only to authenticated users) so that instead of extending System.Web.UI.Page, they will extend the SSOLib.PrivatePage class.
  • In addition to existing codes that perform the log out functionality, call the Logout() method that is already available to the code-behind classes from the SSOLib.PrivatePage base class. Also, instead of executing existing login functionality, call the Login() method of SSOLib.PrivatePage and execute other post-login codes if they exist already.

That’s it! You should be done with your SSO implementation.

Hold on! My pages already extend a base class

OK, there is a high chance that you already have a base class which is extended by the code-behind classes in your ASP.NET applications. If that is so, integrating the SSOLib.PrivatePage may become even easier for you.

Let’s say there is already a BasePage class which is extended by the code-behind classes of the authenticated page (pages which are accessible onto to the authenticated users) in one of your applications. In this case, instead of modifying the code-behind classes of all the ASPX pages, you might just need to modify theBasePage so that it extends SSOLib.PrivatePage, and you are done.

class BasePage : SSOLib.PrivatePage
{
    ...
}

Another alternative is to modify SSOLib.PrivatePage to extend the existing BasePage (you have the source code, you can do it) and modify all the existing aspx.cs classes of the authenticated pages to extendSSOLib.PrivatePage as suggested. That is:

class PrivatePage : BasePage 
{
    ...
}

If there is any conflicting code or method between the existing BasePage class and the SSOLib.PrivatePageclass, you might need to modify some code in these two classes. It would be preferable not to change the code of SSOLib.PrivatePage unless any bug is discovered, and it would be better to change the existing BasePagecode as required. But, feel free to change the code of SSOLib.PrivatePage if you really need to, it’s all yours!

Hmm.. so who does all the SSO things? Where is the magic?

Good question. In the ideal case, using this example SSO model, you won’t have to write a single line of Sign On oriented code to implement SSO in your ASP.NET applications (except some configuration and inheritance changes). How is this possible? Who is managing all the dirty SSO stuff?

SSOLib and the SSO site are the two magicians doing all the tricks. SSOLib is a DLL which is used by each client site to carry out the following things:

  • Communicate to SSO site via a Web Service.
  • Redirect to the SSO site or login page or serve the requested page.

The following diagram depicts the role of SSOLib in the SSO model:

CrossDomainSSOExample/SSOLib.png

The most important thing inside SSOLib is the PrivatePage class which is inherited by the code-behind pages of the authenticated classes. This class inherits the System.Web.UI.Page class, and overrides the OnLoad()method, as follows:

public class PrivatePage : Page
{
      protected override void OnLoad(EventArgs e)
      {
           //Set caching preferences
           SetCachingPreferences();
                      
           //Read QueryString parameter values
           LoadParameters();

           if (IsPostBack)
           {
               //If this is a postback, do not redirect to SSO site.
               //Rather, hit a web method to the SSO site 
               //to know user's logged in status
               //and proceed based on the status
               HandlePostbackRequest();
               base.OnLoad(e);
               return;
           }

           //If the current request is marked not 
           //to be redirected to SSO site, do not proceed
           if (SessionAPI.RequestRedirectFlag == false)
           {
               SessionAPI.ClearRedirectFlag();
               base.OnLoad(e);
               return;
           }

           if (string.IsNullOrEmpty(RequestId))
           {
               //Absence of Request Paramter "RequestId" means 
               //current request is not redirected from SSO site.
               //So, redirect to SSO site with ReturnUrl
               RedirectToSSOSite();
               return;
           }
           else
           {
               //Current request is redirected from 
               //the SSO site. So, check user status
               //And redirect to appropriate page
               ValidateUserStatusAndRedirect();
           }

           base.OnLoad(e);
       }
}

Basically, OnLoad() is called whenever a Page object is loaded as a result of a URL hit in the browser, and the core SSO logic is implemented inside this method. All the codes is self descriptive and documented to depict what is going on.

More on the SSOLib functionality in the following sections.

What does http://www.sso.com do?

The SSO site has the following two important functionalities:

    • User authentication and user retrieval Web Services which are accessed by the client sites via the SSOLib DLL to authenticate the user and to know the user’s logged-in status on the SSO site. The following services are available:

CrossDomainSSOExample/SSOWebServices.png

    • Setting and retrieving user authentication cookie using an ASPX page (Authenticate.aspx) which is redirected by SSOLib for setting / checking or removing the cookie based upon the type of request.

Following is the core functionality that is performed by Authenticate.aspx. The codes is self-descriptive and documented for easy understandability.

protected void Page_Load(object sender, EventArgs e)
{
   //Read request paramters and populate variables
   LoadRequestParams();

   if (Utility.StringEquals(Action, AppConstants.ParamValues.LOGOUT))
   {
       //A Request paramter value Logout indicates
       //this is a request to log out the current user
       LogoutUser();
       return;
   }
   else
   {
       if (Token != null)
       {
           //Token is present in URL request. That means, 
           //user is authenticated at the client site 
           //using the Login screen and it redirected
           //to the SSO site with the Token in the URL parameter, 
           //so set the Authentication Cookie
           SetAuthCookie();
       }
       else
       {
           //User Token is not available in URL. So, check 
           //whether the authentication Cookie is available in the Request
           HttpCookie AuthCookie = 
              Request.Cookies[AppConstants.Cookie.AUTH_COOKIE];
           if (AuthCookie != null)
           {
               //Authentication Cookie is available 
               //in Request. So, check whether it is expired or not.
               //and redirect to appropriate location based upon the cookie status
               CheckCookie(AuthCookie, ReturnUrl);
           }
           else
           {
               //Authentication Cookie is not available 
               //in the Request. That means, user is logged out of the system
               //So, mark user as being logged out
               MarkUserLoggedOut();
           }
       }
   }
}

Looks pretty good. Did you have to handle any critical issues?

Another good question. The core SSO logic seems pretty straightforward. That is:

If current request is a PostBack, 
    If this is a PostBack in Login page (For Login)
        Do Nothing
    Else
        Do not redirect to SSO site. Rather, invoke a web service at SSO site 
        to know user's logged in status, using the User *Token. 
    If user is not logged out 
        Proceed the normal PostBack operation.
    Else 
        Redirect to login page
Else
    If current request is not redirected from the SSO Site, 
        Redirect it to SSO site with   setting ReturnUrl with 
        the current Request URL and parameters.
    Else
        Get user's Logged in status on SSO Site 
        by invoking a web service with user *Token

        If user is logged out there, 
            Redirect to Login page
        If current request is a page refresh, 
            Redirect to SSO site with ReturnUrl
        Else 
            Redirect to the originally requested URL
    End If
End If

*User token is a hash code of a GUID that identifies a user’s login onto the SSO site uniquely. Each time a user is logged onto the SSO site, the token is generated at the SSO site, and this token is used later to set the authentication cookie and to retrieve the user object by the client sites.

But there are some obvious issues that were needed to be handled to implement the SSO logic. These are marked in bold in the above logic:

Implement “Redirect to login page” and “Redirect to the originally requested URL

SSOLib.PrivatePage redirects to the SSO site, or redirects to the currently requested page at the client site, based upon the situation. But, there is a problem if SSOLib.PrivatePage redirects to a page of the current site. As each authenticated page extends the SSOLib.PrivatePage class, a redirect to a page in the current site from SSOLib.PrivatePage would redirect to itself again and again, and will cause an infinite redirect loop.

To solve this issue, an easy fix could be to add a request parameter (say, Redirect=false) to indicate that the request should not be redirected any further. But, this would allow the user to see the Request parameter and allow the user to “hack” the system by altering its value. So, instead of using a Request parameter, I used a Session variable to stop further redirection, before redirecting to any URL of the current site fromSSOLib.PrivatePage. In OnLoad(), I check the Session variable and reset it and return as follows:

//If the current request is marked not to be redirected to SSO site, do not proceed
if (SessionAPI.RequestRedirectFlag == false)
{
   SessionAPI.ClearRedirectFlag();
   return;
}

Detect whether “Current request is not redirected from the SSO Site“, and whether “current request is a page refresh

SSOLib.PrivatePage redirects to the SSO site for setting or checking the authentication cookie. After the SSO site is done with its work, it redirects back to the calling site using the URL that is set in ReturnUrl.

This also creates a scenario where the client site might again redirect to the SSO site and the SSO site again redirects to client site and creates an infinite redirection loop. Unlike the previous situation, this time, a Session variable could not be used because the redirection is occurring from the SSO site, and the client site and the SSO site have different Session states. So, a Request parameter value should be used to prevent further redirect to the SSO site once the SSO site redirects to the client site.

But again, using a Request parameter to prevent redirection would allow the user to alter it and break the normal functionality. To work-around this, the Request parameter value is set with a hash of a GUID(RequestId=Hash(New GUID)), and this is appended from the SSO site before redirecting back to the client-site URL.

The redirect request executes the OnLoad() method of SSOLib.PrivatePage again, and this time, it finds theRequestId, and this indicates that this request is redirected back from the SSO site and hence this should not be redirected to the SSO site further.

But, what if the user alters the value of the RequestId in the query string and hits the URL, or the user just refreshes the current page?

As each different request is to be redirected to the SSO site (except the postback hits), in this case, this request should be redirected to the SSO site as usual. But, the request URL already contains a RequestId, and despite this, the request should be redirected to the SSO site. So, how should SSOLib.PrivatePage understand this?

There is only one way. A specific RequestId should be valid for each particular redirect from the SSO site only, and once the RequestId is received at the client site from the Request parameter, it should expire instantly so that even if the next URL hit contains the same RequstId, or if the next URL contains an invalid value, it redirects to the SSO site.

The following logic has been used to handle this scenario:

if (string.IsNullOrEmpty(RequestId))
{
   //Absence of Request Paramter RequestId means current 
   //request is not redirected from SSO site.
   //So, redirect to SSO site with ReturnUrl
   RedirectToSSOSite();
   return;
}
else
{
   //Current request is redirected from the SSO site. So, check user status
   //And redirect to appropriate page
   ValidateUserStatusAndRedirect();
}

//And,

UserStatus userStatus = AuthUtil.Instance.GetUserStauts(Token, RequestId);
if (!userStatus.UserLoggedIn)
{
   //User is not logged in at SSO site. So, return the Login page to user
   RedirectToLoginPage();
   return;
}
if (!userStatus.RequestIdValid)
{
   //Current RequestId is not valid. That means, 
   //this is a page refresh and hence, redirect to SSO site
   RedirectToSSOSite();
   return;
}
if (CurrentUser == null || CurrentUser.Token != Token)
{
   //Retrieve the user if the user is not found 
   //in session, or, the current user in session
   //is not the one who is currently logged onto the SSO site
   CurrentUser = AuthUtil.Instance.GetUserByToken(Token);
   if (CurrentUser.Token != Token || CurrentUser == null)
   {
       RedirectToSSOSite();
       return;
   }
}

On the other hand, before redirecting to the client site, the SSO site generates a RequestId, appends it with the query string, and puts it in Application using the RequestId as the key and value. Following is how the SSO site redirects back to the client site:

/// <summary>
/// Append a request ID to the URl and redirect
/// </summary>
/// <param name="Url"></param>
private void Redirect(string Url)
{
    //Generate a new RequestId and append to the Response URL.
    //This is requred so that, the client site can always
    //determine whether the RequestId is originated from the SSO site or not
    string RequestId = Utility.GetGuidHash();
    string redirectUrl = Utility.GetAppendedQueryString(Url, 
              AppConstants.UrlParams.REQUEST_ID, RequestId);
    
    //Save the RequestId in the Application
    Application[RequestId] = RequestId;

    Response.Redirect(redirectUrl);
}

Note that, before redirection, RequestId is stored in the Application scope to mark that this RequestId is valid for this particular response to the client site. Once the client site receives the redirected request, it executes the GetUserStatus() Web Service method, and following is how the GetUserStatus() web method clears the RequestId from the Application scope so that any subsequent requests with the same RequestId or any request with an invalid RequestId can be tracked as an invalid RequestId:

/// <summary>
/// Determines whether the current request is valid or not
/// </summary>
/// <param name="RedirectId"></param>
/// <returns></returns>
[WebMethod]
public UserStatus GetUserStauts(string Token, string RequestId)
{
      UserStatus userStatus = new UserStatus();

      if (!string.IsNullOrEmpty(RequestId))
      {
          if ((string)Application[RequestId] == RequestId)

          {
              Application[RequestId] = null;
              userStatus.RequestIdValid = true;
          }
      }

      userStatus.UserLoggedIn = 
        HttpContext.Current.Application[Token] == null ? false : true;

      return userStatus;
}

Get user’s logged in status on the SSO site

The GetUserStauts() Web Service method returns the user’s status inside a UserStatus object, which has two properties: UserLoggedIn and RequestIdValid.

Once a user is logged onto the SSO site via the Authenticate Web Service method, it generates a User Token (hash code of a new GUID) and stores the user Token inside an Application variable using the Token as the Key:

/// <summary>
/// Authenticates user by UserName and Password
/// </summary>
/// <param name="UserName"></param>
/// <param name="Password"></param>
/// <returns></returns>
[WebMethod]
public WebUser Authenticate(string UserName, string Password)
{
   WebUser user = UserManager.AuthenticateUser(UserName, Password);
   if (user != null)
   {
       //Store the user object in the Application scope, 
       //to mark the user as logged onto the SSO site
       //Along with the cookie, this is a supportive way 
       //to trak user's logged in status
       //In order to track a user as logged onto the SSO site 
       //user token has to be presented in the cookie as well as
       //he/she has to be presented in teh Application scope
       HttpContext.Current.Application[user.Token] = user;
   }
   return user;
}

When the user logs out of the system from any client site, the authentication cookie is removed, and also the user object is removed from the Application scope (inside Authenticate.aspx.cs in the SSO site):

/// <summary>
/// Logs out current user;
/// </summary>
private void LogoutUser()
{
   //This is a logout request. So, remove the authentication Cookie from the response
   if (Token != null)
   {
       HttpCookie Cookie = Request.Cookies[AppConstants.Cookie.AUTH_COOKIE];

       if (Cookie.Value == Token)
       {
           RemoveCookie(Cookie);
       }
   }
   //Also, mark the user at the application scope as null
   Application[Token] = null;

   //Redirect user to the desired location
   //ReturnUrl = GetAppendedQueryString(ReturnUrl, 
   //   AppConstants.UrlParams.ACTION, AppConstants.ParamValues.LOGOUT);
   Redirect(ReturnUrl);
}

So, without redirecting to the SSO site, it is possible to know the user’s logged in status just by checking the user’s presence in the Application scope of the SSO site. The client sites invoke the Web Service method of the SSO site, and the SSO site returns the user’s logged in status inside the UserStatus object.

This method of knowing the user’s logged in status is handy because when a postback occurs, the client sites would not want to redirect to the SSO site (because, if they do that, the postback event methods cannot be executed).

In such cases, they invoke the web method to know the user’s logged in status, and if the user is not available at the SSO site, the current request is redirected to the login page. Otherwise, the normal postback event method is executed.

Wait a minute, storing the user in the Application scope should mark the user logged in for all sessions. How do you handle that?

True. Once a user is authenticated, he/she is stored in the Application scope to mark as logged in. But, theApplication scope is a global scope irrespective of the site and user sessions. So, there is a risk that the user might also get marked as logged in for all browser sessions.

This sounds risky. But, this is handled with care so that the user object of a particular browser session is not available to other browser sessions. Let us now see how this has been handled.

Once a user logs onto the SSO site, the user is stored in the Applicationscope against the user Token, which is valid only for a particular user Login session.

If some direct request is hit in a new window (hence with a new Session) with the user Token (with or without the RequestId) by copying the URL from the address bar, the system will not let the URL request bypass the login screen. Why? Because the authentication cookie that is set by the SSO site is a “non-persistent” cookie, and hence this cookie is sent by the browser to the SSO site only if subsequent requests are hit in the same browser session (from the same browser window or different tabs in the same window). That means, if a new browser window is opened, it does not have any authentication cookie to send to the SSO site, and naturally, the request is redirected to the login page of the client site. So, even if a user is stored in the Application scope in the SSO site, that user object is stored against a different user Token as a key, that can never be accessed for any new request in the new session, because this request does not know about the existing user Token, and once the user logs onto this new browser session, it gets a new user Token which never matches with the existing ones.

How cookie timeout and sliding expiration is maintained?

The web.config of the SSO site has configuration options for configuring the cookie timeout value and for enabling/disabling the sliding expiration of the cookie.

<appSettings>
    <add key="AUTH_COOKIE_TIMEOUT_IN_MINUTES" value="30"/>
    <add key="SLIDING_EXPIRATION" value="true"/>
</appSettings>

The cookie timeout value can be configured in the web.config of the SSO site and the timeout value applies to all client sites under the SSO. That is, if the cookie timeout value is specified in the web.config as 30 minutes and ifuser1 logs onto http://www.domain1.com, the cookie is available for the next 30 minutes in the browser, and henceuser1 is signed on the other two sites for this 30 minutes, unless user1 is logged out of the site.

Now, how is this cookie timeout implemented? Simple, by setting the cookie expiration time, of course.

Unfortunately, I couldn’t do that. Why? Because, by default, when a cookie is set in the Response, it is created as a non-persistent cookie (the cookie is stored only in the browser’s memory for the current session, not in the client’s disk). If the expiry date is specified for the cookie, ASP.NET runtime automatically instructs the browser to store the cookie as a persistent cookie.

In our case, we don’t want to create a persistent cookie, because this will let the other sessions to also send the authentication cookie to the SSO site and eventually mark the user as logged in. We do not want that to happen.

But, the expiration datetime has to be set somehow. So, I stored the expiration value in the cookie’s value, along with appending to the user’s Token, as follows:

/// <summary>
/// Set authentication cookie in Response
/// </summary>
private void SetAuthCookie()
{
   HttpCookie AuthCookie = new HttpCookie(AppConstants.Cookie.AUTH_COOKIE);

   //Set the Cookie's value with Expiry time and Token
   int CookieTimeoutInMinutes = Config.AUTH_COOKIE_TIMEOUT_IN_MINUTES;

   AuthCookie.Value = Utility.BuildCookueValue(Token, CookieTimeoutInMinutes);
   //Appens the Token and expiration DateTime to build cookie value

   Response.Cookies.Add(AuthCookie);

   //Redirect to the original site request
   ReturnUrl = Utility.GetAppendedQueryString(ReturnUrl, 
                        AppConstants.UrlParams.TOKEN, Token);
   Redirect(ReturnUrl);
}

/// <summary>
/// Set cookie value using the token and the expiry date
/// </summary>
/// <param name="Value"></param>
/// <param name="Minutes"></param>
/// <returns></returns>
public static string BuildCookueValue(string Value, int Minutes)
{
    return string.Format("{0}|{1}", Value, 
       DateTime.Now.AddMinutes(Minutes).ToString());
}

Eventually, when the cookie is received at the SSO site, its value is retrieved as follows:

/// <summary>
/// Reads cookie value from the cookie
/// </summary>
/// <param name="cookie"></param>
/// <returns></returns>
public static string GetCookieValue(HttpCookie Cookie)
{
   if (string.IsNullOrEmpty(Cookie.Value))
   {
       return Cookie.Value;
   }
   return Cookie.Value.Substring(0, Cookie.Value.IndexOf("|"));
}

And, the expiration date time is retrieved as follows:

/// <summary>
/// Get cookie expiry date that was set in the cookie value
/// </summary>
/// <param name="cookie"></param>
/// <returns></returns>
public static DateTime GetExpirationDate(HttpCookie Cookie)
{
   if (string.IsNullOrEmpty(Cookie.Value))
   {
       return DateTime.MinValue;
   }
   string strDateTime = 
     Cookie.Value.Substring(Cookie.Value.IndexOf("|") + 1);
   return Convert.ToDateTime(strDateTime);
}

If SLIDING_EXPIRATION is set to true in the web.config, the cookie expiration date-time value is increased with each request, with the minute value specified in AUTH_COOKIE_TIMEOUT_IN_MINUTES in the web.config. The following code does that:

/// <summary>
/// Increases Cookie expiry time
/// </summary>
/// <param name="AuthCookie"></param>
/// <returns></returns>
private HttpCookie IncreaseCookieExpiryTime(HttpCookie AuthCookie)
{
   string Token = Utility.GetCookieValue(AuthCookie);
   DateTime Expirytime = Utility.GetExpirationDate(AuthCookie);
   DateTime IncreasedExpirytime = 
     Expirytime.AddMinutes(Config.AUTH_COOKIE_TIMEOUT_IN_MINUTES);

   Response.Cookies.Remove(AuthCookie.Name);

   HttpCookie NewCookie = new HttpCookie(AuthCookie.Name);
   NewCookie.Value = 
     Utility.BuildCookueValue(Token, Config.AUTH_COOKIE_TIMEOUT_IN_MINUTES);

   Response.Cookies.Add(NewCookie);

   return NewCookie;
}

Can this implementation be used for production systems?

Yes! It surely can be used, but before that, some security and other cross-cutting issues have to be addressed. This is just a basic implementation, and I didn’t verify the model with a professional Quality Assurance process (though I did some basic acceptance testing myself). Also, this authentication does not offer the full flexibility and powers that Forms authentication provides. Additionally, it does not have the built-in authorization mechanism of Forms authentication, and hence you might need to write some more customization on the current SSO implementation, based upon your specific requirements.

However, I’ll try to update the SSO model to enrich it with more features and make it robust so that this could be used in commercial systems without requiring any customization.

Any suggestion or feedback is highly welcome. Adios!

REF:

http://www.codeproject.com/Articles/106439/Single-Sign-On-SSO-for-cross-domain-ASP-NET-applic

http://www.codeproject.com/Articles/114484/Single-Sign-On-SSO-for-cross-domain-ASP-NET-appl

[Photograph] Những nhiếp ảnh gia nổi tiếng thế giới chụp cùng bức ảnh làm họ nổi tiếng

Vào năm 2006, Tim Mantoani – một nhiếp ảnh gia Mỹ – đã thuê một máy ảnh chụp bằng film khổ lớn: chiếc Polaroid 20×24 chụp lại chân dung những nhiếp ảnh gia nổi tiếng thế giới đứng cùng bức ảnh đã giúp họ nổi tiếng. Ông lấy tên bộ ảnh là “Behind Photographs” với ý muốn lưu lại chân dung hiện thời của hơn 150 là tác giả đứng phía sau những bức ảnh mà chúng ta vẫn tôn vinh. Mỗi bức ảnh của họ là một câu chuyện lớn cho nhân loại và chính cuộc đời của họ cũng là những câu chuyện lớn trong giới nhiếp ảnh thế giới.

14 copya.

Chiếc máy mà Tim Mantoani sử dụng để thực hiện bộ ảnh này là chiếc Polaroid 20×24. Đó là chiếc máy ảnh thuộc loại “instant camera” chụp film in hình lấy liền khổ rất lớn: 20 inches x 24 inches do hãng Polaroid sản xuất. Hiện thời, dòng máy này rất hiếm trên thế giới nhưng lại nhiều người thích dùng, và ở Mỹ, người ta thường đến một số Studio hoặc đại lý của Polaroid để thuê dùng trong một dự án ảnh nào mà thôi. Hiện tại, loại máy ảnh “íntant camera” khổ nhỏ có khá nhiều do hãng Fujifilm sản xuất và Polaroid chỉ sản xuất máy khổ lớn nhất là 8×10″ mà thôi.

Steve McCurry – Girl In Afghanistan
Steve McCurry: Peshawar, Pakistan 1984. “Tôi đã tìm cô gái này suốt 17 năm và đã gặp vào năm 2002. Cô ấy tên là Sharbat Gula”.
1.

Jeff Widener – Beijing 1989
2.
Harry Benson – The Beatles
Harry Benson: Brian Epstein – người quản lý Beatles – nói rằng họ là số một ở Mỹ và tôi đã đến với họ ở New York năm 1964.
3.

Lyle Owerko – 9/11
Lyle Owerko: Không ai biết sự êm đẹp sẽ trở nên đau đớn tột cùng cho toàn nhân loại vào một thời khắc nào đó . Bức ảnh này chỉ là một góc nhỏ của toàn bộ sự kiện và của hàng ngàn câu chuyện với hàng triệu con người kể cho nhau nghe. Không có chữ viết nào, âm thanh nào, mùi vị nào và kể cả tiếng nói nào có thể đọng lại trong tâm trí tôi vào ngày hôm đó. Tôi chỉ có thể làm một việc là bấm máy ảnh trong cái ngày 9/11 tang thương ấy. Tôi hy vọng mọi vết thương sẽ được chữa lành, sự khôn ngoan và hoà bình sẽ đẩy lùi bóng tối và hận thù, nhân loại đi về phía trước trong ân sủng và bình an của sự hiểu biết.
4.
Marry Ellen Mark – Ringmaster With Elephant
Marry Ellen Mark: Tôi đang cầm bức hình do tôi chụp Ram Singh Prakash và chú voi yêu quý của anh ta vào năm 1990. Bức ảnh thực hiện tại Ấn Độ là một phần trong toàn bộ dự án ảnh “The Great Golden Circus” của tôi. Tôi yêu Ấn Độ. Singh qua đời vài tháng sau khi bức ảnh này được chụp.
5.
Thomas Mangelsen – Brown bear
Thomas Mangelsen: Ảnh chụp tại vườn quốc gia Brooks Falls Katmai National Park, Alaska tháng 7 năm 1988.
6.
David Doubilet – Circle Of Barracuda
David Doubilet: Circle of Barracuda, New Ireland, Papua New Guinea. 70% hành tinh là đại dương và nơi đó chứa những vẻ đẹp vô hạn đang tiềm ẩn. Nơi đó, ánh sáng chuyển biến rất lạ lùng, dường như không có đường thẳng, như một vòng tròn hoàn hảo. Một thế giới không có những góc cạnh.
7.

May Pang – John Lennon
May Pang: Bức ảnh tôi gọi là “chân dung gia đình” chụp tại Long Island Sound NY. vào năm 1974
8.
Meil Leifer – Ali vs. Liston
Neil Leifer: Ali vs. Liston – May 25, 1965, Lewiston, Mayne
9.
Vincent Laforet – Me And My Human
Vincent Laforet: Tôi may mắn được chiêm ngưỡng những điều tuyệt vời trong sự nghiệp từ hai mươi năm trước. Rất nhiều cảnh đẹp mà với người khác có thể là không; hoặc những khoảnh khắc quan trọng của lịch sử hay sự kiện nào đó trong hành trình cuộc sống. Một trong những điều tôi học được qua nhiếp ảnh trên không là không có một bước lùi chân.
10.
Bob Gruen – John Lennon
Bob Gruen: John Lennon gọi tôi chụp ảnh cho trang bìa của Album ‘Walls + Bridges’ ở miền đông New York. Sau khi chụp loạt ảnh cho trang bìa. Tôi hỏi anh có cái áo t-shirt New York City và chúng tôi thực hiện ảnh này.
11.
Elliott Erwitt – Two Dogs With Owner
Elliott Erwitt: Tôi chụp năm 1974 trên đường phố từ căn hộ của tôi ở Central Park – New York.
12.

Lori Grinker – Mike Tyson
Lori Grinker: Mike Tyson – 1980.
13.
Nick Ut – Napalm Attack In Vietnam
Nick Ut: 8/6/1972 tại Trảng Bàng. Bé gái trong ảnh là Kim Phúc khi ấy 9 tuổi trong đợt bom Napalm.
14.
Herman Leonard – Jazz Musicians
Herman Leonard: Tôi chụp vào đầu năm 1948 tại Royal Roost – NY. Đó là một buổi tập duy nhất mà tôi có thể chụp ảnh những người vĩ đại Jazz.
15.
Douglas Kirkland – Marilyn Monroe
16.
Carl Fischer – Muhammad Ali
Carl Fischer: Muhammad Ali, New York, 1967
17.

Các bạn có thể xem đầy đủ với bản thương mại trên Amazon

Nguồn: boredpanda

[Dev Tip] runAllManagedModulesForAllRequests

Recent days, I had debugged to find out: Why Application_AuthenticateRequest() method is called for all requests (I mean that included .css, .js,… requests), that didn’t exist before.

We are changing from form authentication to claim-based authentication. In source code for this change, we have:

<modules runAllManagedModulesForAllRequests=”true”>

This is reason, which I spent a day to detect it. 😦

Setting runAllManagedModulesForAllRequests to “true” is a best practice, but if we have handled modules well and performance is a critical then we can set it become “false”.

Some links:

https://rahulgbhatia.wordpress.com/2013/05/28/asp-net-routing-with-iis-7-runallmanagedmodulesforallrequests-true/

– http://bartwullems.blogspot.co.uk/2012/06/optimize-performance-of-your-web.html

– http://stackoverflow.com/questions/4567844/what-is-the-correct-usage-of-runallmanagedmodulesforallrequests-in-asp-net-mvc