一、概念

  Shiro是一个Java安全框架,可以帮助我们完成:认证、授权、加密、会话管理、与Web集成、缓存等。

 

 

 

Subject:即当前用户,在权限管理的应用程序里往往需要知道谁能够操作什么,谁拥有操作该程序的权利,shiro中则需要通过Subject来提供基础的当前用户信息,Subject 不仅仅代表某个用户,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。

SecurityManager:管理所有Subject,这是Shiro框架的核心组件,可以把他看做是一个Shiro框架的全局管理组件,用于调度各种Shiro框架的服务。

Realm:域,Shiro从从Realm获取安全数据(如用户、角色、权限),可以看成数据库。

 

认证流程:

 

使用流程:

 1. 自定义realm

 

 2.构建SecurityManager环境

 

 3.提交认证,将携带的信息储存在 UsernamePasswordToken中

UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username,password);

 4.获取subject

Subject subject = SecurityUtils.getSubject();

5.登录

subject.login(usernamePasswordToken);

 

 

二、代码

代码层级

 

1.pom文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <artifactId>springboot-shiro-10095</artifactId>
	
	<parent>
	  	<groupId>org.springframework.boot</groupId>
	  	<artifactId>spring-boot-starter-parent</artifactId>
	  	<version>2.0.2.RELEASE</version>
	  	<relativePath/>
  	</parent>
	<dependencies>
		<dependency>
        	<groupId>org.springframework.boot</groupId>
        	<artifactId>spring-boot-devtools</artifactId>
        </dependency>
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.44</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.4</version>
        </dependency>
        <!-- shiro -->
        <dependency>
		    <groupId>org.apache.shiro</groupId>
		    <artifactId>shiro-spring</artifactId>
		    <version>1.3.2</version>
		</dependency>
	</dependencies>
	
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
 
</project>

  

2.application.yml

server:
  port: 10095
spring:
  application:
    name: shiro
#  zipkin:
#    base-url: http://127.0.0.1:10092
#eureka
#eureka: 
#  client:
#    service-url:
#      defaultZone: http://localhost:10090/eureka/
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/shiro?useUnicode=true&characterEncoding=UTF-8
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update
  http:
    encoding:
      charset: utf-8
      enabled: true

 

3.关于shiro的表5张,利用JPA自动生成

(1)User 用户表

/**  
 * All rights Reserved
 * @Title:  User.java   
 * @Package com.yanwu.www.entity   
 * @Description: TODO(用一句话描述该文件做什么)   
 * @author: harvey 
 * @date:   2018年8月30日 下午2:05:58   
 * @version V1.0 
 * @Copyright: 2018
 */
package com.yanwu.www.entity;

import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

/**   
 * @ClassName:  User   
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: harvey
 * @date:   2018年8月30日 下午2:05:58   
 *     
 * @Copyright: 2018 
 */
@Entity(name="user")
public class User {
	@Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    
    private String name;
    private String password;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

    
}

  

(2)Role 角色表

/**  
 * All rights Reserved
 * @Title:  Role.java   
 * @Package com.yanwu.www.entity   
 * @Description: TODO(用一句话描述该文件做什么)   
 * @author: harvey 
 * @date:   2018年8月30日 下午2:07:43   
 * @version V1.0 
 * @Copyright: 2018
 */
package com.yanwu.www.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

/**   
 * @ClassName:  Role   
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: harvey
 * @date:   2018年8月30日 下午2:07:43   
 *     
 * @Copyright: 2018 
 */
@Entity
public class Role {
	@Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String roleName;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }
}

 

(3)Permission 权限表

/**  
 * All rights Reserved
 * @Title:  Permission.java   
 * @Package com.yanwu.www.entity   
 * @Description: TODO(用一句话描述该文件做什么)   
 * @author: harvey 
 * @date:   2018年8月30日 下午2:12:42   
 * @version V1.0 
 * @Copyright: 2018
 */
package com.yanwu.www.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

/**   
 * @ClassName:  Permission   
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: harvey
 * @date:   2018年8月30日 下午2:12:42   
 *     
 * @Copyright: 2018 
 */
@Entity
public class Permission {
	
	@Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
	
    private String permission;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getPermission() {
        return permission;
    }

    public void setPermission(String permission) {
        this.permission = permission;
    }
}

 

(4)UserRole 用户和角色关联

/**  
 * All rights Reserved
 * @Title:  UserRole.java   
 * @Package com.yanwu.www.entity   
 * @Description: TODO(用一句话描述该文件做什么)   
 * @author: harvey 
 * @date:   2018年8月30日 下午2:15:24   
 * @version V1.0 
 * @Copyright: 2018
 */
package com.yanwu.www.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

/**   
 * @ClassName:  UserRole   
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: harvey
 * @date:   2018年8月30日 下午2:15:24   
 *     
 * @Copyright: 2018 
 */
@Entity
public class UserRole {
	@Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
	
	private String userId;
	
	private String roleId;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getUserId() {
		return userId;
	}

	public void setUserId(String userId) {
		this.userId = userId;
	}

	public String getRoleId() {
		return roleId;
	}

	public void setRoleId(String roleId) {
		this.roleId = roleId;
	}
}

  

(5)RolePermission 角色和权限关联

/**  
 * All rights Reserved
 * @Title:  RolePermission.java   
 * @Package com.yanwu.www.entity   
 * @Description: TODO(用一句话描述该文件做什么)   
 * @author: harvey 
 * @date:   2018年8月30日 下午2:17:02   
 * @version V1.0 
 * @Copyright: 2018
 */
package com.yanwu.www.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

/**   
 * @ClassName:  RolePermission   
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: harvey
 * @date:   2018年8月30日 下午2:17:02   
 *     
 * @Copyright: 2018 
 */
@Entity
public class RolePermission {
	
	@Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
	
	private String roleId;
	
	private String permissionId;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getRoleId() {
		return roleId;
	}

	public void setRoleId(String roleId) {
		this.roleId = roleId;
	}

	public String getPermissionId() {
		return permissionId;
	}

	public void setPermissionId(String permissionId) {
		this.permissionId = permissionId;
	}
	
}	

 

4.自定义realm(需要继承AuthorizingRealm)

/**  
 * All rights Reserved
 * @Title:  UserRealm.java   
 * @Package com.yanwu.www.config   
 * @Description: TODO(用一句话描述该文件做什么)   
 * @author: harvey 
 * @date:   2018年8月30日 下午2:48:54   
 * @version V1.0 
 * @Copyright: 2018
 */
package com.yanwu.www.config;

import java.util.List;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.yanwu.www.entity.Permission;
import com.yanwu.www.entity.Role;
import com.yanwu.www.entity.User;
import com.yanwu.www.repository.PermissionRipository;
import com.yanwu.www.repository.RoleRipository;
import com.yanwu.www.repository.UserRipository;

/**   
 * @ClassName:  UserRealm   
 * @Description: 自定义realm   
 * @author: harvey
 * @date:   2018年8月30日 下午2:48:54   
 *     
 * @Copyright: 2018 
 */
@Component
public class MyShiroRealm extends AuthorizingRealm{

	@Autowired
	private UserRipository userRipository;
	
	@Autowired
	private RoleRipository roleRipository;
	
	@Autowired
	private PermissionRipository permissionRipository;
	
	/**   
	 * <p>Title: doGetAuthorizationInfo</p>   
	 * <p>Description: </p>   
	 * @param arg0
	 * @return   
	 * @see org.apache.shiro.realm.AuthorizingRealm#doGetAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection)   
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
		
		//获取登录用户名
        String username= (String) principalCollection.getPrimaryPrincipal();
        //查询用户名称
        User user = userRipository.findByName(username);
        
        //添加角色和权限
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        List<Role> roles = roleRipository.findRolesByUserId(user.getId().toString());
        for(Role role : roles){
        	// 添加角色
        	simpleAuthorizationInfo.addRole(role.getRoleName());
        	for(Permission permission : permissionRipository.findPermissionsByRoleId(role.getId().toString())){
        		// 添加权限
        		simpleAuthorizationInfo.addStringPermission(permission.getPermission());
        	}
        }
        
        return simpleAuthorizationInfo;
		
	}

	/**   
	 * <p>Title: doGetAuthenticationInfo</p>   
	 * <p>Description: </p>   
	 * @param arg0
	 * @return
	 * @throws AuthenticationException   
	 * @see org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken)   
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		
		// 1.把AuthenticationToken转为UsernamePasswordToken对象
		UsernamePasswordToken upToken = (UsernamePasswordToken) token;

		// 2.从UsernamePasswordToken获取username
		String userName = upToken.getUsername();

		// 3.调用数据库方法,从数据库中查询username对应的用户记录
		System.out.println("从数据库中获取信息userName:" + userName + "所对应信息");
		User user = userRipository.findByName(userName);
		
		// 4.若用户不存在,则可以抛出异常
		if (null == user) {
			throw new UnknownAccountException("用户不存在");
		}
		
		// 5.根据用户情况,来构建AuthenticationInfo对象并返回,通常使用的实现类是SimpleAuthenticationInfo
		
		// 1)principal,用户名,认证实体,可以是实体,也可以是数据表对应的实体类对象
		Object principal = userName;
		
		// 2)credential,密码,明文密码,即构建UsernamePasswordToken对象时的密码
		Object credentials = user.getPassword().toString();
		
		// 3)realmName:当前realm对象的name,调用父类的getName即可
		String realmName = getName();
		
		// 4.盐值(避免同一密码加密时产生相同的字符串,一般是用用户名做盐值)
		ByteSource credentialsSalt = ByteSource.Util.bytes(userName);

		// 不加密
		//SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, realmName);
		
		// 加密
		SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(principal,credentials, credentialsSalt, realmName);

		return info;
	}
	
	
	// 增加用户时可以使用SimpleHash产生加密后的密码字符串存入数据库,避免数据库的用户密码明文显示
	public static void main(String[] args) {
		String algorithmName="MD5";
		Object source="1234";
		Object salt=ByteSource.Util.bytes("user2");
		int hashIterations=1024;
		Object result=new SimpleHash(algorithmName, source, salt, hashIterations);
		System.out.println(result);
	}

}

 

5.shiro配置类

/**  
 * All rights Reserved
 * @Title:  ShiroConfig.java   
 * @Package com.yanwu.www.config   
 * @Description: TODO(用一句话描述该文件做什么)   
 * @author: harvey 
 * @date:   2018年8月30日 下午2:47:16   
 * @version V1.0 
 * @Copyright: 2018
 */
package com.yanwu.www.config;

import java.util.HashMap;
import java.util.Map;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**   
 * @ClassName:  ShiroConfig   
 * @Description:shiro配置类   
 * @author: harvey
 * @date:   2018年8月30日 下午2:47:16   
 *     
 * @Copyright: 2018 
 */
@Configuration
public class ShiroConfig {
	
	
	/**
     * 密码校验规则HashedCredentialsMatcher
     * 这个类是为了对密码进行编码的 ,
     * 防止密码在数据库里明码保存 , 当然在登陆认证的时候 ,
     * 这个类也负责对form里输入的密码进行编码
     * 处理认证匹配处理器:如果自定义需要实现继承HashedCredentialsMatcher
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        //指定加密方式为MD5
        credentialsMatcher.setHashAlgorithmName("MD5");
        //加密次数
        credentialsMatcher.setHashIterations(1024);
        credentialsMatcher.setStoredCredentialsHexEncoded(true);
        return credentialsMatcher;
    }
	
	//将自己的验证方式加入容器
    @Bean
    public MyShiroRealm myShiroRealm() {
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        
        // 设置加密方式
        myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        
        return myShiroRealm;
    }

    //权限管理,配置主要是Realm的管理认证
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        
        return securityManager;
    }

    //Filter工厂,设置对应的过滤条件和跳转条件
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String,String> map = new HashMap<String, String>();
        
        //anon表示可以匿名访问,authc表示需要认证
        //登出
        map.put("/logout","anon");
        //对所有用户认证 
        map.put("/**","authc");
        //登录
        shiroFilterFactoryBean.setLoginUrl("/login");
        
        //首页
        shiroFilterFactoryBean.setSuccessUrl("/index");
        
        //错误页面,认证不通过跳转
        shiroFilterFactoryBean.setUnauthorizedUrl("/error");
        
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

    //加入注解的使用,不加入这个注解不生效
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
    
}

 

6.Repositoty

(1)BaseRepository

package com.yanwu.www.repository;

import java.io.Serializable;

import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
/**
 * 
 * @ClassName:  BaseRepository   
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: harvey
 * @date:   2018年8月30日 下午2:21:18   
 *   
 * @param <T>
 * @param <I>  
 * @Copyright: 2018
 */
@NoRepositoryBean
public interface BaseRepository<T,I extends Serializable> extends PagingAndSortingRepository<T,I>,JpaSpecificationExecutor<T>{

}

 

(2)UserRipository

/**  
 * All rights Reserved
 * @Title:  UserRipository.java   
 * @Package com.yanwu.www.repository   
 * @Description: TODO(用一句话描述该文件做什么)   
 * @author: harvey 
 * @date:   2018年8月30日 下午2:20:19   
 * @version V1.0 
 * @Copyright: 2018
 */
package com.yanwu.www.repository;

import org.springframework.stereotype.Repository;

import com.yanwu.www.entity.User;

/**   
 * @ClassName:  UserRipository   
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: harvey
 * @date:   2018年8月30日 下午2:20:19   
 *     
 * @Copyright: 2018 
 */
@Repository
public interface UserRipository extends BaseRepository<User, Long>{
	
	User findByName(String username);
}

  

(3)RoleRipository

/**  
 * All rights Reserved
 * @Title:  UserRipository.java   
 * @Package com.yanwu.www.repository   
 * @Description: TODO(用一句话描述该文件做什么)   
 * @author: harvey 
 * @date:   2018年8月30日 下午2:20:19   
 * @version V1.0 
 * @Copyright: 2018
 */
package com.yanwu.www.repository;

import java.util.List;

import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import com.yanwu.www.entity.Role;

/**   
 * @ClassName:  UserRipository   
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: harvey
 * @date:   2018年8月30日 下午2:20:19   
 *     
 * @Copyright: 2018 
 */
@Repository
public interface RoleRipository extends BaseRepository<Role, Long>{
	
	@Query(value = "select distinct r.* from role r inner join role_permission rp on rp.role_id = r.id inner join user_role ur on ur.role_id = r.id where ur.user_id =?1" ,nativeQuery=true)
	List<Role> findRolesByUserId(String userId);
}

  

(4)PermissionRipository

/**  
 * All rights Reserved
 * @Title:  UserRipository.java   
 * @Package com.yanwu.www.repository   
 * @Description: TODO(用一句话描述该文件做什么)   
 * @author: harvey 
 * @date:   2018年8月30日 下午2:20:19   
 * @version V1.0 
 * @Copyright: 2018
 */
package com.yanwu.www.repository;

import java.util.List;

import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import com.yanwu.www.entity.Permission;

/**   
 * @ClassName:  UserRipository   
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: harvey
 * @date:   2018年8月30日 下午2:20:19   
 *     
 * @Copyright: 2018 
 */
@Repository
public interface PermissionRipository extends BaseRepository<Permission, Long>{
	
	@Query(value = "select distinct p.*  from permission p  inner join role_permission rp on rp.permission_id = p.id inner join role r on r.id = rp.role_id  where r.id =?1" ,nativeQuery=true)
	List<Permission> findPermissionsByRoleId(String roleId);
}

 

7.service

(1)UserService

/**  
 * All rights Reserved
 * @Title:  UserService.java   
 * @Package com.yanwu.www.service   
 * @Description: TODO(用一句话描述该文件做什么)   
 * @author: harvey 
 * @date:   2018年8月30日 下午2:25:11   
 * @version V1.0 
 * @Copyright: 2018
 */
package com.yanwu.www.service;

/**   
 * @ClassName:  UserService   
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: harvey
 * @date:   2018年8月30日 下午2:25:11   
 *     
 * @Copyright: 2018 
 */
public interface UserService {
	/**
	 * 
	 * @Title: login   
	 * @Description: 用户登录   
	 * @param username
	 * @param password
	 * @return
	 * @return: String
	 */
	String login(String username,String password);
	
	/**
	 * 
	 * @Title: logout   
	 * @Description: 用户登出   
	 * @return
	 * @return: String
	 */
	String logout();
}

 

(2)UserServiceImpl

/**  
 * All rights Reserved
 * @Title:  UserServiceImpl.java   
 * @Package com.yanwu.www.service   
 * @Description: TODO(用一句话描述该文件做什么)   
 * @author: harvey 
 * @date:   2018年8月30日 下午2:27:15   
 * @version V1.0 
 * @Copyright: 2018
 */
package com.yanwu.www.service;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

/**   
 * @ClassName:  UserServiceImpl   
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: harvey
 * @date:   2018年8月30日 下午2:27:15   
 *     
 * @Copyright: 2018 
 */
@Component
public class UserServiceImpl implements UserService {

	/**   
	 * <p>Title: login</p>   
	 * <p>Description: </p>   
	 * @param username
	 * @param password   
	 * @see com.yanwu.www.service.UserService#login(java.lang.String, java.lang.String)   
	 */
	@Override
	public String login(String username, String password) {
		
		if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){
			throw new UnknownAccountException("账号或者密码为空");
		}
		
		UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username,password);
		
		Subject subject = SecurityUtils.getSubject();
		
		try{
			subject.login(usernamePasswordToken);
			
			// 设置闲置session时间
			subject.getSession().setTimeout(5*1000);
			return "login ok";
		}catch( AuthenticationException e){
			System.out.println("==========");
			System.out.println(e.getMessage());
		}
		
		return "login failure";

	}

	/**   
	 * <p>Title: logout</p>   
	 * <p>Description: </p>   
	 * @return   
	 * @see com.yanwu.www.service.UserService#logout()   
	 */
	@Override
	public String logout() {
		
		Subject subject = SecurityUtils.getSubject();
		
		subject.logout();
		
		return "logout ok";
	}
}

  

8.controller

/**  
 * All rights Reserved
 * @Title:  UserController.java   
 * @Package com.yanwu.www.controller   
 * @Description: TODO(用一句话描述该文件做什么)   
 * @author: harvey 
 * @date:   2018年8月30日 下午3:31:43   
 * @version V1.0 
 * @Copyright: 2018
 */
package com.yanwu.www.controller;

import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.yanwu.www.service.UserService;

/**   
 * @ClassName:  UserController   
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: harvey
 * @date:   2018年8月30日 下午3:31:43   
 *     
 * @Copyright: 2018 
 */
@RestController
public class UserController {
	
	@Autowired
	private UserService userService;
	
	//登录
    @RequestMapping(value = "/login")
    public String login(String username,String password){
    	
    	String status = userService.login(username, password);
    	
        return status;
    }
    
    //首页
    @RequestMapping(value = "/index")
    public String index(){
    
        return "index";
    }
	
	//登出
    @RequestMapping(value = "/logout")
    public String logout(){
    	
    	userService.logout();
    	
        return "logout";
    }

    //错误页面展示
    @RequestMapping(value = "/error",method = RequestMethod.POST)
    public String error(){
        return "error ok!";
    }
    
    // 测试shiro注解
    @RequestMapping(value = "/test",method = RequestMethod.GET)
    @RequiresRoles(value={"admin"})
    public String test(){
        return "test ok!";
    }
    
    
}

  

三、注意点

加密

本博客已经配置,需要在自定义realm,securityManager进行修改,如下配置如何获得加密后的字符串

// 增加用户时可以使用SimpleHash产生加密后的密码字符串存入数据库,避免数据库的用户密码明文显示
public static void main(String[] args) {
  String algorithmName="MD5";
  Object source="1234";
  // 加盐
  Object salt=ByteSource.Util.bytes("user2");
  int hashIterations=1024;
  Object result=new SimpleHash(algorithmName, source, salt, hashIterations);
  System.out.println(result);
}

  

版权声明:本文为harvey2017原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/harvey2017/p/9565288.html