7、ssm整合shiro
来源:互联网 发布:大数据世界txt下载 编辑:程序博客网 时间:2024/04/18 14:31
1、每个管理系统都需要登陆,那么,安全和权限的问题随之而来,主流的是shiro和spring security两种框架实现,今天我们先以shiro为例来做一个简单的登陆验证、以及权限控制的实例吧!
2、项目架构(ssm搭建步骤详情看我前面的博客)
3、实现的效果
4、首先是引入依赖:
<shiro.version>1.3.1</shiro.version><!--shiro--><dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>${shiro.version}</version></dependency><dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>${shiro.version}</version></dependency><dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>${shiro.version}</version></dependency>
5、web.xml中增加shiro过滤器:
<!--shiro权限验证--><filter><filter-name>shiroFilter</filter-name><filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class><async-supported>true</async-supported><init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value></init-param></filter><filter-mapping><filter-name>shiroFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
6、spring-shiro.xml文件:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <!-- 继承自AuthorizingRealm的自定义Realm,即指定Shiro验证用户登录 --> <bean id="myRealm" class="com.oursnail.login.security.MyRealm"> <property name="credentialsMatcher" ref="passwordMatcher"/> </bean> <!--自定义密码校验--> <bean id="passwordMatcher" class="com.oursnail.login.security.CustomCredentialsMatcher"/> <!-- Shiro默认会使用Servlet容器的Session,可通过sessionMode属性来指定使用Shiro原生Session --> <!-- 即<property name="sessionMode" value="native"/>,详细说明见官方文档 --> <!-- 这里主要是设置自定义的单Realm应用,若有多个Realm,可使用'realms'属性代替 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="myRealm"/> </bean> <!-- Shiro主过滤器本身功能十分强大,其强大之处就在于它支持任何基于URL路径表达式的、自定义的过滤器的执行 --> <!-- Web应用中,Shiro可控制的Web请求必须经过Shiro主过滤器的拦截,Shiro对基于Spring的Web应用提供了完美的支持 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- Shiro的核心安全接口,这个属性是必须的 --> <property name="securityManager" ref="securityManager"/> <!-- 要求登录时的链接(可根据项目的URL进行替换),非必须的属性,默认会自动寻找Web工程根目录下的"/login.jsp"页面 --> <property name="loginUrl" value="/login"/> <!-- 登录成功后要跳转的连接(本例中此属性用不到,因为登录成功后的处理逻辑在LoginController里硬编码为main.jsp了) --> <!-- <property name="successUrl" value="/system/main"/> --> <!-- 用户访问未对其授权的资源时,所显示的连接 --> <!-- 若想更明显的测试此属性可以修改它的值,如unauthor.jsp,然后用[玄玉]登录后访问/admin/listUser.jsp就看见浏览器会显示unauthor.jsp --> <!--<property name="unauthorizedUrl" value="/user/denied"/>--> <!-- Shiro连接约束配置,即过滤链的定义 --> <!-- 此处可配合我的这篇文章来理解各个过滤连的作用http://blog.csdn.net/jadyer/article/details/12172839 --> <!-- 下面value值的第一个'/'代表的路径是相对于HttpServletRequest.getContextPath()的值来的 --> <!-- anon:它对应的过滤器里面是空的,什么都没做,这里.do和.jsp后面的*表示参数,比方说login.jsp?main这种 --> <!-- authc:该过滤器下的页面必须验证后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter --> <property name="filterChainDefinitions"> <value> /static/**=anon <!--anon 表示匿名访问,不需要认证以及授权--> /login/**=anon <!--其他所有的都需要权限才能访问--> /**=authc </value> </property> </bean> <!-- 保证实现了Shiro内部lifecycle函数的bean执行 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> <!-- 定义需要特殊处理的异常,用类名或完全路径名作为key,异常页名作为值 --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="org.apache.shiro.authz.UnauthorizedException">/denied</prop> </props> </property> </bean></beans>
这段代码的主要作用是:制定自定义的Realm用于身份的验证以及密码的校验。下面可以设置不需要授权的路径等,我这里主要设置静态资源和login都不需要认证,其他的都需要认证才能访问。
7、spring-mvc.xml中增加一条配置:
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"> <property name="proxyTargetClass" value="true" /></bean><bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"/></bean>
光在spring-shiro.xml配置lifecycle还不够,还需要再spring-mvc中配置这段话,否则不起错用。
8、这样,shiro就配置好了,下面新建一张权限表和一张角色表:
CREATE TABLE `t_role` (`id` int(11) NOT NULL AUTO_INCREMENT ,`role_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,PRIMARY KEY (`id`));CREATE TABLE `t_permission` (`id` int(11) NOT NULL AUTO_INCREMENT ,`permission_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,`role_id` int(11) NULL DEFAULT NULL ,PRIMARY KEY (`id`))
9、用户表
CREATE TABLE `t_user` (`id` int(11) NOT NULL AUTO_INCREMENT ,`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,`role_id` int(11) NULL DEFAULT 1 ,PRIMARY KEY (`id`))
10、下面就是先写一个login.jsp页面:
配置一个路径跳转到login.jsp:
@RequestMapping("")public String login(){ return "login/login";}
<div style="text-align: left;border-color: grey;"> <h3>登陆</h3> <form action="/login/doLogin" method="post"> username:<input name="username" /><br><br> password:<input type="password" name="password" /><br><br> <input type="submit" value="submit"/> </form></div>
提交到的controller对应处理是:
@RequestMapping(value = "/doLogin",method = RequestMethod.POST) public String doLogin(@RequestParam String username, @RequestParam String password, Model model,HttpSession session){ Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username, password); token.setRememberMe(true); try { subject.login(token); User loginUser = (User)session.getAttribute("loginUser"); model.addAttribute("loginUser",loginUser); return "/login/index"; }catch (Exception e){ return "/login/login"; } }
11、执行login方法时就会到realm中验证:
public class MyRealm extends AuthorizingRealm { @Autowired private UserService userService; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { String username = principalCollection.getPrimaryPrincipal().toString() ; SimpleAuthorizationInfo info = new SimpleAuthorizationInfo() ; Set<String> roleNames = userService.findRoles(username) ; Set<String> permissions = userService.findPermissions(username) ; info.setRoles(roleNames); info.setStringPermissions(permissions); return info; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken)token; String username = usernamePasswordToken.getUsername(); System.out.println("======="+username); User user = userService.getUserByName(username); if(user == null){ return null; }else { AuthenticationInfo info = new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),getName()); SecurityUtils.getSubject().getSession().setAttribute("loginUser",user); return info; } }}
先执行 doGetAuthenticationInfo方法实现用户信息的验证。这个先判断用户名正确不正确,然后下面CustomCredentialsMatcher.java中判断密码:
public class CustomCredentialsMatcher extends SimpleCredentialsMatcher { @Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { try { UsernamePasswordToken usertoken = (UsernamePasswordToken) token; String password = String.valueOf(usertoken.getPassword()); Object tokenCredentials = MD5Util.encryptPassword(password); Object accountCredentials =getCredentials(info); return equals(tokenCredentials,accountCredentials); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return false; }}
密码匹配和加密的工具类:
public class MD5Util { /*MD5加密方法*/ public static String encryptPassword(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException { MessageDigest md5 = MessageDigest.getInstance("MD5"); //防止加密字符串乱码情况 BASE64Encoder base64Encoder = new BASE64Encoder(); String result = base64Encoder.encode(md5.digest(password.getBytes("utf-8"))); return result; } /*判断密码是否相等*/ public static boolean checkPassword(String inputPwd,String dbPwd) throws UnsupportedEncodingException, NoSuchAlgorithmException { String result = encryptPassword(inputPwd); if(result.equals(dbPwd)){ return true; }else { return false; } } public static void main(String[] args) throws Exception{ String result = MD5Util.encryptPassword("123"); System.out.println("result:"+result); }}
一致的话,就不会抛任何异常,controll层顺利跳转。
12、进去之后,如果根据不同的角色和赋予这个角色的权限访问不同的资源呢?
实现就是有依靠realm中的doGetAuthorizationInfo 方法判断,在这个方法里,拿到用户相应的角色和权限的集合,至于集合信息怎么拿呢?
UserMapper.Java中:
Set<String> findRoles(String username);Set<String> findPermissions(String username);
UserMapper.xml:
<select id="findRoles" parameterType="String" resultType="String">select r.role_name from t_user u,t_role r where u.role_id=r.id and u.username=#{username}</select><select id="findPermissions" parameterType="String" resultType="String">select p.permission_name from t_user u,t_role r,t_permission pwhere u.role_id=r.id and p.role_id=r.id and u.username=#{username}</select>
拿到之后,我们就知道这个用户是什么角色,有什么权限了,在这个简单的系统里,swg用户角色是user,权限是user:;hh用户角色是admin,权限是admin:;我们通过注解的方式可以实现权限的控制:
比如我规定user/user这条路径是需要认证的,然后user和admin用户都可以访问;但是user/admin这个路径只能是admin用户访问,如果user用户访问了,就显示拒绝访问的提示。
@RequestMapping("/user") public String user(){ return "/user/user";}@RequiresRoles("admin")@RequestMapping("/admin")public String admin(){ return "/user/admin";}
一个简单的注解就可以实现角色的控制了。上面提到,如果没有权限,应该给一个提示页面,这种方式变焦友好,在spring-shiro.xml中的配置,提到如果是没有权限的话,就到denied这个页面,我们直接在viesw目录下新建一个denied.jsp页面即可,它会自动跳转。
13、源码下载
14、我依据曾经的这些笔记整理而得:
我的有道云整理笔记1
我的有道云整理笔记2
我的有道云整理笔记3
可以花半天学习一下视频,讲的很好。获取密码是3oqs
- 7、ssm整合shiro
- ssm整合shiro
- ssm+shiro+UEditor整合
- SSM+shiro整合
- SSM整合shiro完整版
- shiro与SSM项目整合
- shiro与SSM项目整合
- Maven+SSM+Shiro整合配置
- ssm整合shiro实现权限
- Maven+SSM+Shiro整合配置
- SSM+shiro+maven整合配置
- Maven+SSM+Shiro整合配置
- springmvc SSM java redis shiro ehcache 整合
- SSM springmvc mybatis 整合 bootstrap maven shiro
- 把Shiro整合到SSM框架中
- ssm+shiro整合 (未测试版本)
- SSM + Shiro 整合 (6)- Shiro 集成 Spring
- idea ssm整合shiro shiro的基本用法
- 数组指针,指针数组,函数指针,等理解
- C语言基础操作符整理~
- fpt配置
- NTFS文件系统详解
- 你知道哪些聊天机器人
- 7、ssm整合shiro
- Linux环境下安装redis集群
- 过度理想化与造梦周期
- Canny源码理解
- nginx的优先匹配规则
- 关于hbase修复
- kali中怎么安装Nessus
- IntelliJ IDEA Ultimate 2017激活方法
- Nginx Location配置总结