MySQL database table: teacher (user), role (role),perms (permission)
The teacher table
Role table
Perms table
Shiro is a security framework for authentication, authorization, password encryption, and session management.
Subject: the Subject represents the current “user”. This user is not necessarily a specific person. Anything that interacts with the current application is a Subject, such as web crawlers, robots, etc. It’s an abstract concept; All subjects are bound to the SecurityManager, and all interactions with the Subject are delegated to the SecurityManager; You can think of a Subject as a facade; The SecurityManager is the actual enforcer;
SecurityManager: SecurityManager; That is, all security-related operations interact with the SecurityManager; And it manages all subjects; As you can see, this is the core of Shiro. It is responsible for interacting with the other components described later. If you have learned SpringMVC, you can think of it as a DispatcherServlet front-end controller.
Realm: realms. Shiro gets security data (such as users, roles, and permissions) from a Realm. This means that SecurityManager needs to authenticate a user, then it needs to get the corresponding user from a Realm and compare it to determine if the user’s identity is valid. You also need to get the user’s roles/permissions from the Realm to verify that the user can perform operations; A Realm can be thought of as a DataSource, a secure DataSource.
Use:
Introduction of depend on
</dependency> <! <groupId>org.apache.shiro</groupId> <artifactId> <version>1.4. 0</version>
</dependency>
Copy the code
Rely on other
<! <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> <version>2.11..RELEASE</version> <! Use shiro tags - thymeleaf page - > < the dependency > < groupId > com. Making. Theborakompanioni < / groupId > <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.0. 0</version> </dependency> <! -- Shiro integrated EhCache -->Copy the code
Configure the ShiroConfig class and custom Realm
ShiroConfig starts with three beans
/ / create ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// Set the security manager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// Add Shiro built-in filters
/*Shiro has built-in filters that implement permit-related interceptors * anon: the resource can be accessed without authentication * authc: the resource must be authenticated * user: the resource can be accessed directly if you use the rememberMe function * perms: The resource can be accessed only if the resource has been granted resource permission * role: the resource can be accessed only if the role permission has been granted * * */
Map<String,String> filterMap = new LinkedHashMap<>();
filterMap.put("/test"."anon");
filterMap.put("/login"."anon");
filterMap.put("/doRegister"."anon");
filterMap.put("/register"."anon");
// Authorization filter
// Current authorization is blocked and Shiro automatically jumps to the unauthorized page
filterMap.put("/add"."perms[user:add]");
filterMap.put("/update"."perms[user:update]");
filterMap.put("/ *"."authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
// Default to login. JSP, change to toLogin
shiroFilterFactoryBean.setLoginUrl("/toLogin");
// Set the unauthorized page
shiroFilterFactoryBean.setUnauthorizedUrl("/unAuth");
return shiroFilterFactoryBean;
}
Copy the code
/ / create DefaultWebSecurityManager
@Bean("securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
/ / associated Realm
securityManager.setRealm(userRealm);
//
securityManager.setSessionManager( getDefaultWebSessionManager() );
return securityManager;
}
/ / create a Realm
@Bean("userRealm")
public UserRealm getRealm(a){
return new UserRealm();
}
Copy the code
Custom Realm Userrealm. Java
Inheritance: Extends AuthorizingRealm overrides two methods
// Execute the authorization logic
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("Enforcement authorization");
return null;
}
// Execute authentication logic
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("Performing certification");
}
Copy the code
Ctrl layer
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(name,password);
Copy the code
Log on to the subject. The login (token);
Appropriate subject. Logout ();
Rights management Obtain role and rights during authentication
List<Role> rlist = rMapper.roleList(login.getRid());// Obtain the user role
List<Perms> plist = pMapper.permList(login.getRid());// Obtain user rights
List<String> roleStrlist=new ArrayList<>();//// User role set
List<String> perminsStrlist=new ArrayList<>();// Set of permissions for the user
for (Role role : rlist) {
roleStrlist.add(role.getRole_name());
}
for(Perms uPermission : plist) { perminsStrlist.add(uPermission.getPerm()); } login.setRoleStrlist(roleStrlist); login.setPerminsStrlist(perminsStrlist); Add permission when authorization SimpleAuthorizationInfo info =new SimpleAuthorizationInfo();
// Set of user roles
info.addRoles(teacher.getRoleStrlist());
// Set of permissions for the userinfo.addStringPermissions(teacher.getPerminsStrlist()); Add two beans to the Shiroconfig class, define the encryption method, and inject@Bean("hashedCredentialsMatcher")
public HashedCredentialsMatcher hashedCredentialsMatcher(a) {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("MD5");// Hash algorithm: MD5 algorithm is used here;
hashedCredentialsMatcher.setHashIterations(1024);// The number of hashes, such as two hashes, is equivalent to md5(md5(""));
hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);// Hexadecimal or not
return hashedCredentialsMatcher;
}
/** * authentication realm */
@Bean("myShiroRealm")
public UserRealm myShiroRealm(a){
UserRealm myShiroRealm = new UserRealm();
myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
System.out.println("MyShiroRealm injection successful");
returnmyShiroRealm; } SimpleAuthenticationInfo info = for Realm authenticationnull;
String realname = getName();
// The salt value is encrypted. The user name can be used
ByteSource salt = ByteSource.Util.bytes(tname);
info = new SimpleAuthenticationInfo(login,login.getPassword(),salt, realname);
Session session = SecurityUtils.getSubject().getSession();
session.setAttribute("USER_SESSION", login); Salt: Increases the complexity of encryption and adds hashCopy the code
MD5 encryption method in Shiro
ByteSource credentialsSalt01 = ByteSource.Util.bytes("Zhang");
Object credential = "123456";/ / password
String hashAlgorithmName = "MD5";// Encryption mode
//1024 indicates the number of times of encryption
Object simpleHash = new SimpleHash(hashAlgorithmName, credential,
credentialsSalt01, 1024);
System.out.println("Encrypted value ----->" + simpleHash)
Copy the code
Caching mechanisms
Why cache? On the page to access some role or permissions to access the url, you will find that every visit to take corresponding to the role of the users to have access to the database, imagine, every time I visit a url, repeated to the database with these data, is clearly a not mature practice, if a cache, we only need to query a database, After that, all access to the URL will take data from the cache rather than the database, which will significantly reduce database pressure and look relatively mature. Add the dependent
Add bean Shiroconfig@Bean
public EhCacheManager getCacheManager(a){
EhCacheManager ehCacheManager = new EhCacheManager();
//ehCacheManager.setCacheManagerConfigFile("src\\main\\resources\\shiro-ehcache.xml");
returnehCacheManager; } is added to the securityManager securityManager. SetCacheManager (getCacheManager ()); Log in to Shiroconfig again// Prohibit repeat logins
/ / configuration sessionDAO
@Bean(name="sessionDAO")
public MemorySessionDAO getMemorySessionDAO(a){
MemorySessionDAO sessionDAO = new MemorySessionDAO();
return sessionDAO;
}
// Configure a manager for Shiro sessions
@Bean(name = "sessionManager")
public DefaultWebSessionManager getDefaultWebSessionManager(a){
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
// Set the session expiration time
sessionManager.setGlobalSessionTimeout(60*60*1000);
// Look at the code
sessionManager.setSessionDAO(getMemorySessionDAO());
// Resolve the issue of urls carrying JessionIds
sessionManager.setSessionIdUrlRewritingEnabled(false);
returnsessionManager; } Realm: delete session// Prohibit simultaneous login
if( tname.equals( login.getName() ) && md5.equals( login.getPassword() ) ){
// Get all sessions
Collection<Session> sessions = sessionDAO.getActiveSessions();
for (Session session: sessions) {
Teacher sysUser = (Teacher) session.getAttribute("USER_SESSION");
// If there is a current login in the session, then it is proved that the login is repeated, then it is removed
System.out.println("seesion:"+session.getId());
if( sysUser! =null) {if( tname.equals( sysUser.getName() ) ){
session.setTimeout(0); }}}}Copy the code
other
// Configure ShiroDialect for thymeleaf and Shiro tags
@Bean
public ShiroDialect getShiroDialect(a){
return new ShiroDialect();
}
Copy the code