架构

屏幕快照 2019-04-22 22.49.46.png

核心是SecurityManager

认证是通过调用Authenticator来实现的,authenticator内部又是调用realm的doGetAuthenticationInfo实现

  1. protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
  2. assertRealmsConfigured();
  3. Collection<Realm> realms = getRealms();
  4. if (realms.size() == 1) {
  5. return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken);
  6. } else {
  7. return doMultiRealmAuthentication(realms, authenticationToken);
  8. }
  9. }
  10. doSingleRealmAuthentication
  11. AuthenticationInfo info = realm.getAuthenticationInfo(token);
  12. info = doGetAuthenticationInfo(token);
  13. //SimpleAccountRealm.java
  14. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  15. UsernamePasswordToken upToken = (UsernamePasswordToken) token;
  16. SimpleAccount account = getUser(upToken.getUsername());
  17. if (account != null) {
  18. if (account.isLocked()) {
  19. throw new LockedAccountException("Account [" + account + "] is locked.");
  20. }
  21. if (account.isCredentialsExpired()) {
  22. String msg = "The credentials for account [" + account + "] are expired";
  23. throw new ExpiredCredentialsException(msg);
  24. }
  25. }
  26. return account;
  27. }
  28. //拿到AuthenticationInfo后使用assertCredentialsMatch(token,info)进行账户、密码比对
  29. public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  30. AuthenticationInfo info = getCachedAuthenticationInfo(token);
  31. if (info == null) {
  32. //otherwise not cached, perform the lookup:
  33. info = doGetAuthenticationInfo(token);
  34. log.debug("Looked up AuthenticationInfo [{}] from doGetAuthenticationInfo", info);
  35. if (token != null && info != null) {
  36. cacheAuthenticationInfoIfPossible(token, info);
  37. }
  38. } else {
  39. log.debug("Using cached authentication info [{}] to perform credentials matching.", info);
  40. }
  41. if (info != null) {
  42. assertCredentialsMatch(token, info);
  43. } else {
  44. log.debug("No AuthenticationInfo found for submitted AuthenticationToken [{}]. Returning null.", token);
  45. }
  46. return info;
  47. }
  48. //assertCredentialsMatch(token,info)内部又调用了SimpleCredentialsMatcher.doCredentialsMatch比对
  49. public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
  50. Object tokenCredentials = getCredentials(token);
  51. Object accountCredentials = getCredentials(info);
  52. return equals(tokenCredentials, accountCredentials);
  53. }

同理,授权也是通过调用authorizer来实现,authorize内部调用realm的doGetAuthorizationInfo实现

认证

WechatIMG16.jpeg

  1. package com.twx.shiro;
  2. import org.apache.shiro.SecurityUtils;
  3. import org.apache.shiro.authc.UsernamePasswordToken;
  4. import org.apache.shiro.mgt.DefaultSecurityManager;
  5. import org.apache.shiro.realm.SimpleAccountRealm;
  6. import org.apache.shiro.subject.Subject;
  7. import org.junit.Before;
  8. import org.junit.Test;
  9. public class AuthenticationTest {
  10. SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
  11. @Before
  12. public void addUser(){
  13. simpleAccountRealm.addAccount("mark","123456");
  14. }
  15. @Test
  16. public void testAuthentication(){
  17. //1.构建SecruityManager环境
  18. DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
  19. defaultSecurityManager.setRealm(simpleAccountRealm);
  20. //2. 主体提交认证请求
  21. SecurityUtils.setSecurityManager(defaultSecurityManager);
  22. Subject subject = SecurityUtils.getSubject();
  23. UsernamePasswordToken token = new UsernamePasswordToken("mark","123456");
  24. subject.login(token);
  25. System.out.println("isAuthenticated: "+subject.isAuthenticated());
  26. subject.logout();
  27. System.out.println("isAuthenticated: "+subject.isAuthenticated());
  28. }
  29. }

授权

WechatIMG15.jpeg

  1. package com.twx.shiro;
  2. import org.apache.shiro.SecurityUtils;
  3. import org.apache.shiro.authc.UsernamePasswordToken;
  4. import org.apache.shiro.mgt.DefaultSecurityManager;
  5. import org.apache.shiro.realm.SimpleAccountRealm;
  6. import org.apache.shiro.subject.Subject;
  7. import org.junit.Before;
  8. import org.junit.Test;
  9. public class AuthenticationTest {
  10. SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
  11. @Before
  12. public void addUser(){
  13. simpleAccountRealm.addAccount("mark","123456","admin","dev");
  14. }
  15. @Test
  16. public void testAuthentication(){
  17. //1.构建SecruityManager环境
  18. DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
  19. defaultSecurityManager.setRealm(simpleAccountRealm);
  20. //2. 主体提交认证请求
  21. SecurityUtils.setSecurityManager(defaultSecurityManager);
  22. Subject subject = SecurityUtils.getSubject();
  23. UsernamePasswordToken token = new UsernamePasswordToken("mark","123456");
  24. subject.login(token);
  25. System.out.println("isAuthenticated: "+subject.isAuthenticated());
  26. // subject.checkRole("admin");
  27. subject.checkRoles("admin","dev");
  28. subject.logout();
  29. System.out.println("isAuthenticated: "+subject.isAuthenticated());
  30. }
  31. }