Shiro集成Spring详细步骤
1.导包
为了方便直接导入Shiro所有的jar包
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.2.3</version>
</dependency>
2.在web.xml文件配置Shiro拦截器
<!--配置Shiro过滤器-->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern> <!--让shiro拦截所有请求-->
</filter-mapping>
3.配置Shiro配置文件
1.配置过滤器
bean的id名要和filter-name名字一样
默认:
anon 放行
authc 拦截
<!--配置过滤器-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManage"/>
<property name="loginUrl" value="index.jsp"/> <!--配置登录页面-->
<property name="unauthorizedUrl" value="404.jsp"/> <!--配置不需要认证的页面-->
<!--配置过滤链-->
<property name="filterChainDefinitions">
<value>
/index.jsp = anon <!--放行-->
/login = anon <!--这里是Controller里登录方法的url也要放行-->
/* = authc <!--拦截-->
</value>
</property>
</bean>
2.配置shiro核心对象SecurityManage
注意是导包是DefaultWebSecurityManager,不是DefaultSecurityManager 。如果导包导错web端会报错
<!--配置安全管理员-->
<bean id="securityManage" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="realm"/>
</bean>
3.配置自定义realm
<!--配置自定义Realm-->
<bean id="realm" class="com.hwua.util.CustomRealm">
<property name="credentialsMatcher" ref="credentialsMatcher"></property>
</bean>
4.配置加密算法
<!--配置加密算法-->
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher" id="credentialsMatcher">
<property name="hashAlgorithmName" value="md5"></property> <!--使用md5算法-->
<property name="hashIterations" value="1"></property> <!--次数1次-->
</bean>
4.数据库表的关系
首先先看下数据库三张表中的关系
第一张表用户表:用户ID、用户账户、用户密码
第二张表角色表:角色id、用户名/用户id、角色名
第三表权限表:权限id、角色名、角色的权限
三张表的关系是:通过用户名—>找到角色定位,再通过角色定位——>找到对应的权限,通过权限可以展示指定的菜单
5.编写Mapper层和Service层
Mapper层
@Mapper
public interface UsersMapper {
/**
* 通过用户名查找用户信息
* @param name
* @return
*/
@Select({"select * from users where username = #{name}"})
public abstract Users finUserByName(@Param("name") String name);
/**
* 通过用户名查找角色
* @param name
* @return
*/
@Select("select id,username,role_name as roleName from user_role where username = #{name}")
public abstract List<UserRole> findRoleByUNAME(String name);
/**
* 通过用户名查找角色的权限
* @param rName
* @return
*/
@Select("select * from role_permission where role_name = #{rName}")
public abstract List<RolePermission> findPermissionByRName(String rName);
}
Service层
@Service
public class UserService {
@Autowired
UsersMapper usersMapper;
/**
* 根据用户名查询user
* @param name
* @return
*/
public Users UserByName(String name){
return usersMapper.finUserByName(name);
}
/**
* 根据用户名查询角色定位
* @param name
* @return
*/
public Set<String> RoleByName(String name){
List<UserRole> roles = usersMapper.findRoleByUNAME(name);
Set<String> set = new HashSet<String>();
for (UserRole role : roles) {
set.add(role.getRoleName());
}
return set;
}
/**
* 根据角色名查询可访问的资源
* @param name
* @return
*/
public Set<String> permissionByRName(String name){
//通过username查询到角色定位结果集
Set<String> roleName = RoleByName(name);
Set<String> set = new HashSet<String>();
for (String role : roleName) {
//通过角色查到对应的权限对象
List<RolePermission> rpList = usersMapper.findPermissionByRName(role);
//把权限结果集进行提取封装
for (RolePermission permission : rpList) {
set.add(permission.getPermission());
}
}
return set;
}
}
6.编写自定义的Realm
//自定义Realm
public class CustomRealm extends AuthorizingRealm {
@Autowired
UserService userService;
/**
* 权限管理
* @param principalCollection
* @return
*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取主体的用户名
String username = (String)principalCollection.getPrimaryPrincipal();
//创建simpleAuthorizationInfo对象作为返回值
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//查询角色
Set<String> roles = userService.RoleByName(username);
//查询权限
Set<String> permissions = userService.permissionByRName(username);
simpleAuthorizationInfo.setStringPermissions(permissions);
simpleAuthorizationInfo.setRoles(roles);
return simpleAuthorizationInfo;
}
/**
* 认证管理
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//通过主体传过来的获取username
String username = (String)authenticationToken.getPrincipal();
//通过用户名获取password
Users users = userService.UserByName(username);
if (users==null){
return null;
}
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,users.getPassword(),"customRealm");
//返回的值加上盐
simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("abc"));
return simpleAuthenticationInfo;
}
}
7.编写Controller层
@Controller
public class UserController {
@RequestMapping(value = "/login",method = RequestMethod.GET)
public String login(Users users){
//获得主体
Subject subject = SecurityUtils.getSubject();
//创建Token
UsernamePasswordToken token = new UsernamePasswordToken(users.getUsername(),users.getPassword());
//判断是否认证成功
try {
subject.login(token);
}catch (Exception e){
return "404";
}
//判断是否有admin权限
if (subject.hasRole("admin")){
System.out.println("admin");
return "admin";
}
return "success";
}
}
8.最终效果
张三有admin权限进行登录
王五没有admin权限
第一次写博客,如果技术当中有错误的地方欢迎指出,不喜勿喷,谢谢!