任何框架要用首先要到pom依赖 。。。
在shiro.xml配置文件配置shiro相关信息
因为securityManager需要realm
package com.ssq.realm;
import com.ssq.pojo.User;
import com.ssq.service.RoleService;
import com.ssq.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
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 java.util.Set;
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService us;
@Autowired
private RoleService rs;
/**
* 授权
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
User user= (User) principals.getPrimaryPrincipal();
//根据用户名去获取账户的角色和权限
Set<String> roles= rs.findRoles(user.getLoginName());
Set<String> permissions= rs.findPermissions(user.getLoginName());
SimpleAuthorizationInfo sai = new SimpleAuthorizationInfo();
//把查出的权限给SimpleAuthorizationInfo 进行判断
sai.addRoles(roles);
sai.addStringPermissions(permissions);
return sai;
}
/**
* 认证
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username =(String) token.getPrincipal();
User user= us.findByLoginName(username);
//判断用户不存在
if (user==null) {
throw new UnknownAccountException();
}
return new SimpleAuthenticationInfo(
user,//用户信息 用户对象
user.getPassword(),//密码
ByteSource.Util.bytes(user.getLoginName()),//salt
getName()//realm的名称
);
}
}
我在java类里写了关于realm
这个类里的realm通过service去找dao dao去找mapper 根据用户名查出该用户的角色和权限
@RequestMapping("/login")
public String login(String loginName, String password, Model model, HttpSession session){
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token=new UsernamePasswordToken(loginName,password);
try {
subject.login(token);
User user = (User) subject.getPrincipal();
//http提供的session
//session.setAttribute("user",user);
//使用shiro提供的session
System.out.println(subject.getSession()==session);
subject.getSession().setAttribute("user",user);
//http的session与shiro是一样的
return "forward:/product/findAll";
}catch (UnknownAccountException e){
model.addAttribute("loginError","用户名不存在");
}catch (IncorrectCredentialsException e){
model.addAttribute("loginError","密码不正确");
}catch (AuthenticationException e){
model.addAttribute("loginError","登陆失败");
}
return "login";
}
这是controller里的
还有配置shiro过滤规则 只有把所有请求经过shiro过滤器 shiro 才能对所有请求进行拦截 然后进行认证授权
package com.ssq.filter;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
* 自定义角色验证过滤器
*/
public class CustomRolesAuthorizationFilter extends AuthorizationFilter {
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object o)
throws Exception {
Subject subject=getSubject(request,response);
String[] rolesArray=(String[]) o;
if (rolesArray==null||rolesArray.length==0){
return true;
}
//判断角色 只要要任何一个角色就可以访问
for (int i=0;i<rolesArray.length;i++){
if (subject.hasRole(rolesArray[i])) {
return true;
}
}
return false;
}
}
然后在shiro配置文件里配置
<bean id="customRoles" class="com.ssq.filter.CustomRolesAuthorizationFilter"/>
以及web.xml过滤器
<!--配置Shiro过滤器 用来拦截所有请求 进行认证和授权-->
<!--然后在spring-shiro配置文件中 配置和这里一模一样的名字的bean shrioFilter-->
<filter>
<filter-name>shrioFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>transformWsdlLocations</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shrioFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1.首先是密码加密
package com.ssq.service.impl;
import com.ssq.vo.PasswordVo;
import org.apache.shiro.authc.credential.PasswordService;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
public class PasswordServiceImpl implements PasswordService {
@Value("${algorithmName}")
private String algorithmName;
@Value("${hashIterations}")
private int hashIterations;
@Override
public String encryptPassword(Object PasswordVo) throws IllegalArgumentException {
PasswordVo Vo = (com.ssq.vo.PasswordVo) PasswordVo;
return new SimpleHash(algorithmName,Vo.getPassword(),Vo.getSalt(),hashIterations).toBase64();
}
@Override
public boolean passwordsMatch(Object submittedPlaintext, String encrypted) {
return false;
}
}
在service层调用
package com.ssq.service.impl;
import com.ssq.dao.UserDao;
import com.ssq.pojo.User;
import com.ssq.service.UserService;
import com.ssq.vo.PasswordVo;
import org.apache.shiro.authc.credential.PasswordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.Map;
@Service
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
public class UserServiceImpl implements UserService {
@Autowired
private UserDao ud;
@Autowired
private PasswordService ps;
@Override
public int register(Map<String, Object> map) {
//对明文密码进行加密
PasswordVo vo=new PasswordVo();
String password = (String) map.get("password");
System.out.println("密码:"+password);
String loginName =(String) map.get("loginName");
System.out.println("用户名:"+loginName);
vo.setPassword(password);
vo.setSalt(loginName);
//加密后的密码
String str = ps.encryptPassword(vo);
Map<String,Object> map1=new HashMap<>();
map1.put("loginName",loginName);
map1.put("password",str);
return ud.register(map1);
}
这是vo
package com.ssq.vo;
import java.io.Serializable;
public class PasswordVo implements Serializable {
private String password;
private String salt;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt;
}
}
并在配置文件properties里配置算法以及散列次数
然后就是controller调用service
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService us;
//注册
@RequestMapping("/register")
public String register(String loginName,String password){
Map<String,Object> map=new HashMap<>();
map.put("loginName",loginName);
map.put("password",password);
us.register(map);
return "login";
}
然后就是密码解密 登录
//登录
@RequestMapping("/login")
public String login(String loginName, String password, Model model, HttpSession session){
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token=new UsernamePasswordToken(loginName,password);
try {
subject.login(token);
User user = (User) subject.getPrincipal();
//http提供的session
//session.setAttribute("user",user);
//使用shiro提供的session
System.out.println(subject.getSession()==session);
subject.getSession().setAttribute("user",user);
//http的session与shiro是一样的
return "forward:/product/findAll";
}catch (UnknownAccountException e){
model.addAttribute("loginError","用户名不存在");
}catch (IncorrectCredentialsException e){
model.addAttribute("loginError","密码不正确");
}catch (AuthenticationException e){
model.addAttribute("loginError","登陆失败");
}
return "login";
}
登录也就是解密
/**
* 认证
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username =(String) token.getPrincipal();
User user= us.findByLoginName(username);
//判断用户不存在
if (user==null) {
throw new UnknownAccountException();
}
return new SimpleAuthenticationInfo(
user,//用户信息 用户对象
user.getPassword(),//密码
ByteSource.Util.bytes(user.getLoginName()),//salt
getName()//realm的名称
);
}
}
realm需要密码匹配器
<!--配置密码匹配器-->
<!--realm需要密码匹配器-->
<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!--密码匹配器需要算法-->
<!--这个就是encrypt.properties里面配置好的算法以及散列次数 以后只需改那里面的就行-->
<property name="hashAlgorithmName" value="${algorithmName}"></property>
<!--散列次数-->
<property name="hashIterations" value="${hashIterations}"></property>
<!--在UserServiceImpl中用的编码方式是tobase64 而默认的编码方式是16进制-->
<!--所以我们需要将默认改为false-->
<property name="storedCredentialsHexEncoded" value="false"></property>
</bean>
登陆成功 根据用户名查询该用户的拥有什么权限和角色
<mapper namespace="com.ssq.dao.RoleDao">
<select id="selectRoles" resultType="string" parameterType="string">
select tr.role_name
from shiro.t_user tu
left join shiro.user_role ur
on tu.id=ur.user_id
left join shiro.t_role tr
on ur.role_id=tr.id
where tu.login_name=#{username}
</select>
<select id="selectPermissions" resultType="string" parameterType="string">
select tp.permission_name
from shiro.t_user tu
left join shiro.user_role ur
on tu.id=ur.user_id
left join shiro.t_role tr
on ur.role_id=tr.id
left join shiro.role_permisstion rp
on rp.role_id=tr.id
left join shiro.t_permisstion tp
on tp.id=rp.permission_id
where tu.login_name=#{username}
</select>
<!--定义一个名为shrioFilter的 这里的bean的id要与web.xml配置的shiro过滤器名称一致-->
<!--用来配置url过滤规则-->
<bean id="shrioFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!--配置securityManager-->
<property name="securityManager" ref="securityManager"></property>
<!--配置url过滤规则-->
<property name="filterChainDefinitions">
<value>
<!--anon不需要登陆认证-->
<!--authc需要登陆认证-->
/showLogin= anon
/product/**=authc
/teacher/delete=authc,perms[teacher:delete]
<!--这里要重写权限的验证 默认是并且的关系 我们这里重写后 登陆者只需要满足其中一个角色即可-->
/teacher/**=authc,customRoles[teacher,manager]
/student/**=authc,roles[student]
</value>
</property>
来源:CSDN
作者:Ttogether_i
链接:https://blog.csdn.net/Ttogether_i/article/details/104798602