二、RememberMe
The user's access to the page is divided into three levels:
Unauthenticated-accessible page-(stranger)-greeting
login.html、regist.html
Remember me-accessible page-(ex-girlfriend)-hug between friends
info.html
Verified—Accessible Page—(Current Girlfriend)—Holding Hands
Transfer.html
2.1 Set "remember me" accessible url in the filter
// anon 表示未认证可访问的url
// user 表示记住我可访问的url(已认证也可以访问),例如某些页面在之前登陆过,安全级别又不高时,可以在用户再次浏览时呈现,这时可以设置为user
//authc 表示已认证可访问的url,对于某些安全级别很高的,即使几天或几小时之前登陆过,但是在再次进行操作时还必须得确认登陆或安全性时,比如付款时再次确认用户身份,这时可以设置为authc
//perms 表示必须具备指定的权限才可访问
//logout 表示指定退出的url
filterMap.put("/","anon");
// 为user表示"记住我",但是当用户需要一些其他的认证才能访问时,必须要进行验证才能访问
// user要比authc低一等级
filterMap.put("/index.html","user");
filterMap.put("/login.html","anon");
filterMap.put("/regist.html","anon");
filterMap.put("/user/login","anon");
filterMap.put("/user/regist","anon");
filterMap.put("/layui/**","anon");
filterMap.put("/**","authc");
filterMap.put("/c_add.html","perms[sys:c:save]");
filterMap.put("/exit","logout");
2.2 Configure the cookie-based rememberMe manager in ShiroConfig.java
@Bean
public CookieRememberMeManager cookieRememberMeManager(){
CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
//cookie必须设置name
SimpleCookie cookie = new SimpleCookie("rememberMe");
cookie.setMaxAge(30*24*60*60);
rememberMeManager.setCookie(cookie);
return rememberMeManager;
}
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(MyRealm myRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myRealm);
securityManager.setCacheManager(getEhCacheManager());
securityManager.setSessionManager(getDefaultWebSessionManager());
//设置remember管理器
securityManager.setRememberMeManager(cookieRememberMeManager());
return securityManager;
}
2.3 Set the token "remember me" during login authentication
-
log in page
<form action="/user/login" method="post">
<p>帐号:<input type="text" name="userName"/></p>
<p>密码:<input type="text" name="userPwd"/></p>
<p>记住我:<input type="checkbox" name="rememberMe"/></p>
<p><input type="submit" value="登录"/></p>
</form>
-
Controller
@Controller
@RequestMapping("user")
public class UserController {
@Resource
private UserServiceImpl userService;
@RequestMapping("login")
public String login(String userName,String userPwd,boolean rememberMe){
try {
userService.checkLogin(userName,userPwd,rememberMe);
System.out.println("------登录成功!");
return "index";
} catch (Exception e) {
System.out.println("------登录失败!");
return "login";
}
}
//...
}
-
service
@Service
public class UserServiceImpl {
public void checkLogin(String userName, String userPwd,boolean rememberMe) throws Exception {
//Shiro进行认证 ——入口
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(userName,userPwd);
token.setRememberMe(rememberMe);
subject.login(token);
}
}
Three, Shiro multi-Realm configuration
3.1 Usage scenarios
-
When shiro performs permission management and the data comes from different data sources, we can configure multiple Realms for SecurityManager
|
3.2 How to deal with multiple Realms
3.2.1 Chain processing
-
Multiple Realms are authenticated in turn. As long as one Realm is successfully authenticated, it means that the authentication is successful, but all the set Realms must be authenticated each time.
3.2.2 Branch processing
-
Select one of multiple Realms for authentication processing according to different conditions
3.3 Multiple Realm configuration (chain processing)
-
Define multiple Realms
-
UserRealm
public class UserRealm extends AuthorizingRealm { Logger logger = LoggerFactory.getLogger(UserRealm.class); @Override public String getName() { return "UserRealm"; } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { return null; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { logger.info("--------------------------------UserRealm"); //从token中获取username UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; String username = token.getUsername(); //根据username从users表中查询用户信息 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username,"123456",getName()); return info; } }
-
ManagerRealm
public class ManagerRealm extends AuthorizingRealm { Logger logger = LoggerFactory.getLogger(ManagerRealm.class); @Override public String getName() { return "ManagerRealm"; } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { return null; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { logger.info("--------------------------------ManagerRealm"); //从token中获取username UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; String username = token.getUsername(); //根据username从吗managers表中查询用户信息 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username,"222222",getName()); return info; } }
-
-
Configure multiple Realms for SecurityManager in ShiroConfig.java
@Configuration public class ShiroConfig { @Bean public UserRealm userRealm(){ UserRealm userRealm = new UserRealm(); return userRealm; } @Bean public ManagerRealm managerRealm(){ ManagerRealm managerRealm = new ManagerRealm(); return managerRealm; } @Bean public DefaultWebSecurityManager getDefaultWebSecurityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //securityManager中配置多个realm Collection<Realm> realms = new ArrayList<>(); realms.add(userRealm()); realms.add(managerRealm()); securityManager.setRealms(realms); return securityManager; } //... }
-
Test code:
-
login.html
<form action="user/login" method="post"> <p>帐号:<input type="text" name="userName"/></p> <p>密码:<input type="text" name="userPwd"/></p> <p><input type="radio" name="loginType" value="User"/>普通用户 <input type="radio" name="loginType" value="Manager"/>管理员</p> <p><input type="submit" value="登录"/></p> </form>
-
UserController.java
@Controller @RequestMapping("user") public class UserController { Logger logger = LoggerFactory.getLogger(UserController.class); @RequestMapping("login") public String login(String userName,String userPwd, String loginType){ logger.info("~~~~~~~~~~~~~UserController-login"); try{ UsernamePasswordToken token = new UsernamePasswordToken(userName,userPwd); Subject subject = SecurityUtils.getSubject(); subject.login(token); return "index"; }catch (Exception e){ return "login"; } } }
-
3.4 Shiro authentication processing source code analysis
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
this.assertRealmsConfigured();
Collection<Realm> realms = this.getRealms();
// this.doMultiRealmAuthentication(realms, authenticationToken);中的realms参数就是认证会执行的Realm
return realms.size() == 1 ? this.doSingleRealmAuthentication((Realm)realms.iterator().next(), authenticationToken) : this.doMultiRealmAuthentication(realms, authenticationToken);
}
3.5 Multiple Realm configuration (branch processing)
Execute different Realm according to different conditions
-
Process analysis
-
Implementation case: users log in with different identities to execute different Realms
-
Custom Realm (UserRealm\ManagerRealm)
-
When you select "Ordinary User" to log in on the login page, the UserRealm authentication is performed
-
When you select "Administrator" on the login page to log in, ManagerRealm authentication is performed
-
-
Realm's declaration and configuration
-
Custom Token
public class MyToken extends UsernamePasswordToken { private String loginType; public MyToken(String userName,String userPwd, String loginType) { super(userName,userPwd); this.loginType = loginType; } public String getLoginType() { return loginType; } public void setLoginType(String loginType) { this.loginType = loginType; } }
-
Custom authenticator
public class MyModularRealmAuthenticator extends ModularRealmAuthenticator { Logger logger = LoggerFactory.getLogger(MyModularRealmAuthenticator.class); @Override protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException { logger.info("------------------------------MyModularRealmAuthenticator"); this.assertRealmsConfigured(); Collection<Realm> realms = this.getRealms(); MyToken token = (MyToken) authenticationToken; String loginType = token.getLoginType(); // User logger.info("------------------------------loginType:"+loginType); Collection<Realm> typeRealms = new ArrayList<>(); for(Realm realm:realms){ if(realm.getName().startsWith(loginType)){ //UserRealm typeRealms.add(realm); } } if(typeRealms.size()==1){ return this.doSingleRealmAuthentication((Realm)typeRealms.iterator().next(), authenticationToken); }else{ return this.doMultiRealmAuthentication(typeRealms, authenticationToken); } } }
-
Configure a custom authenticator
@Configuration public class ShiroConfig { @Bean public UserRealm userRealm(){ UserRealm userRealm = new UserRealm(); return userRealm; } @Bean public ManagerRealm managerRealm(){ ManagerRealm managerRealm = new ManagerRealm(); return managerRealm; } @Bean public MyModularRealmAuthenticator myModularRealmAuthenticator(){ MyModularRealmAuthenticator myModularRealmAuthenticator = new MyModularRealmAuthenticator(); return myModularRealmAuthenticator; } @Bean public DefaultWebSecurityManager getDefaultWebSecurityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //配置自定义认证器(放在realms设置之前) securityManager.setAuthenticator(myModularRealmAuthenticator()); //securityManager中配置多个realm Collection<Realm> realms = new ArrayList<>(); realms.add(userRealm()); realms.add(managerRealm()); securityManager.setRealms(realms); return securityManager; } //... }
-
Test: The controller accepts data for certification
-
login.html
<form action="user/login" method="post"> <p>帐号:<input type="text" name="userName"/></p> <p>密码:<input type="text" name="userPwd"/></p> <p><input type="radio" name="loginType" value="User" checked/>普通用户 <input type="radio" name="loginType" value="Manager"/>管理员</p> <p><input type="submit" value="登录"/></p> </form>
-
UserController.java
@Controller @RequestMapping("user") public class UserController { Logger logger = LoggerFactory.getLogger(UserController.class); @RequestMapping("login") public String login(String userName,String userPwd, String loginType){ logger.info("~~~~~~~~~~~~~UserController-login"); try{ //UsernamePasswordToken token = new UsernamePasswordToken(userName,userPwd); MyToken token = new MyToken(userName,userPwd,loginType); Subject subject = SecurityUtils.getSubject(); subject.login(token); return "index"; }catch (Exception e){ return "login"; } } }
-
-
4. List of single project development technologies
4.1 JSP application
-
View JSP(Java Server Page)
-
Control Servlet
-
Model JDBC(Java Database Connection)
-
The first phase of the project: JSP/Servlet+JDBC
4.2 SSM
-
View JSP
-
Control SpringMVC
-
Model MyBatis
-
The second stage project: JSP+SSM
4.3 SpringBoot
-
View Thymeleaf
-
Control SpringMVC
-
Model MyBatis/tkMapper
-
The third stage practice project: thymeleaf+SpringBoot (SSM)
Monolithic project: The front-end page of the project and the server-side code are in the same project (deployed on the same server)
|
VX can be added for technical exchanges or learning resources:
For the technical language learning of development technology, such as java, android, python, etc., I summarized a series of videos for 2020. I hope everyone can help each other at work, all for life, give yourself a chance, a little time, and double your salary. , Will life still be as bitter as it is now?